mysql - 使用 FirstOrDefault 与 ToArray 的 LINQ 查询

标签 mysql sql .net performance linq

使用 MySQL 5.6 和以下表结构:

CREATE TABLE `dataitem` (
  `AI` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `ID` binary(16) NOT NULL,
  `OwnerID` binary(16) NOT NULL,
  `DataItemTimeUtc` datetime NOT NULL,
  `DataItemTimeLocal` datetime NOT NULL,
  `DataItemTimeMicroSeconds` int(11) NOT NULL,
  `DataItemArrivalTimeUtc` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
  `DataItemTimeTimeZoneID` binary(16) NOT NULL,
  `QuestionID` binary(16) NOT NULL,
  `QuestionHistoryID` binary(16) DEFAULT NULL,
  `QuestionAbsolutePositionID` varchar(1000) COLLATE utf8_unicode_ci DEFAULT NULL,
  `GroupSessionIDString` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
  `DataItemType` int(11) NOT NULL,
  `DataEntryDevice` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
  `DataEntryDeviceCradle` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
  `DataItemXml` longtext COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`AI`),
  UNIQUE KEY `dataitem_ID_UQ_Idx` (`ID`),
  KEY `dataitem_OwnerID_Idx` (`OwnerID`),
  KEY `dataitem_DataItemTimeUtc_Idx` (`DataItemTimeUtc`),
  KEY `dataitem_QuestionID_Idx` (`QuestionID`),
  KEY `dataitem_QuestionHistoryID_Idx` (`QuestionHistoryID`),
  KEY `dataitem_QuestionAbsolutePositionID_Idx` (`QuestionAbsolutePositionID`(255)),
  KEY `dataitem_DataItemType_Idx` (`DataItemType`)
) ENGINE=InnoDB AUTO_INCREMENT=23467 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

我正在经历一些我难以理解的事情。以下查询会导致 fatal error ,因为它需要很长时间才能执行:

        Guid patientid = new Guid("cfed2acf-acbd-4ab2-8c23-7ab0b3a8cfa3");
        var latestRecord = (from f in QueryHelper.GetEntityTable<DataItem>()
                              where
                              f.OwnerID == patientid
                              && f.QuestionAbsolutePositionID == "5867FF5EC08B9C0422EFD1359B2802B29A8E167952D381EC70AE53CE6D4C9318"
                              orderby f.DataItemTimeUtc descending
                              select f.ID).FirstOrDefault();

但是,如果我将 .FirstOrDefault() 更改为 .ToArray(),查询将像闪电一样运行并返回 2 个结果。谁能解释一下?

从 .ToArray() 生成的 SQL 查询:

SELECT t0.`ID`
FROM `DataItem` AS t0
WHERE ((t0.`OwnerID` = @p0) AND (t0.`QuestionAbsolutePositionID` = @p1))
ORDER BY t0.`DataItemTimeUtc` DESC
-- p0 = [cfed2acf-acbd-4ab2-8c23-7ab0b3a8cfa3]
-- p1 = [5867FF5EC08B9C0422EFD1359B2802B29A8E167952D381EC70AE53CE6D4C9318]

从 .FirstOrDefault() 生成的 SQL 查询:

SELECT t0.`ID`
FROM `DataItem` AS t0
WHERE ((t0.`OwnerID` = @p0) AND (t0.`QuestionAbsolutePositionID` = @p1))
ORDER BY t0.`DataItemTimeUtc` DESC
LIMIT 0, 1
-- p0 = [cfed2acf-acbd-4ab2-8c23-7ab0b3a8cfa3]
-- p1 = [5867FF5EC08B9C0422EFD1359B2802B29A8E167952D381EC70AE53CE6D4C9318]

最佳答案

首先,弄清楚为什么 QuestionAbsolutePositionID 需要 1000 个字符长。它可以小于 256,让它如此。如果不行,那就问问自己能不能改成CHARACTER SET ascii。它看起来像十六进制,可以很好地与 ascii 配合使用。 (“ids”很少包括重音字母、西里尔字母、日语等)如果这些“修复”都不可能,你能升级到 MySQL 5.7 吗?

一旦解决了索引大小的问题(如上),添加这个“复合”(和“覆盖”)索引;它应该加快查询速度:

INDEX(OwnerID, QuestionAbsolutePositionID, DataItemTimeUtc, ID)

(前两列可以任意排序。)

如果没有帮助,那么我们需要讨论@variables。

关于mysql - 使用 FirstOrDefault 与 ToArray 的 LINQ 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40810518/

相关文章:

php - 如何对不同行中堆叠的值求和? PHP PDO MYSQL

MySQL "Foreign key constraint is incorrectly formed"

SQLSTATE[HY000] : General error: 1 no such table

php - Laravel 5.1 Eloquent 查询语法

c# - 位图和 hBitmap 内存泄漏

mysql - 有效地将许多相似的记录插入MySQL

php - 上传多个实例时需要重命名文件的帮助

sql - 如何在 SQL 中每列值只选择一行?

.net - 是否有 “free” 替代 .NET Reflector?

c# - 防止显示 Windows 安全窗口