NOT EXISTS 条件下的查询速度问题

Query Speed Issue with NOT EXISTS condition

我有一个有效的查询,但速度很慢。有没有办法加快速度?基本上我有一个带有时间卡条目的 table,然后是第二个 table,带有该条目的时间细分,与 TimecardID 相关。我正在寻找的是没有故障的时间段。我想如果我把标准降低到 2 个月,它会加快速度。感谢您的帮助

SELECT * FROM Timecards
WHERE NOT EXISTS (SELECT TimeCardID FROM TimecardBreakdown WHERE Timecards.ID = TimecardBreakdown.TimeCardID) 
AND Status <> 0
AND DateIn >= CURRENT_DATE() - INTERVAL 2 MONTH

您似乎想知道 Timecardbreakdown table 中不存在的 TimecardID,此时您可以使用左外连接。

 SELECT a.*
 FROM Timecards a
 LEFT OUTER JOIN TimecardBreakdown b ON a.TimecardID = b.TimecardID
 WHERE b.TimecardID IS NULL

这将摆脱子查询(这是昂贵的)并使用连接(它更有效)。

MySQL 快速执行相关子查询很糟糕。尝试使您的子查询独立并加入它们。您可以使用 LEFT JOIN ... IS NULL 模式替换 WHERE NOT EXISTS.

SELECT tc.*
  FROM Timecards tc
  LEFT JOIN TimecardBreakdown tcb ON tc.ID = tcb.TimeCardId
 WHERE tc.DateIn >= CURRENT_DATE() - INTERVAL 2 MONTH
   AND tc.Status <> 0
   AND tcb.TimeCardId IS NULL

一些优化点。

首先,如果您可以将 tc.Status <> 0 更改为 tc.Status > 0,则可以对该列进行索引范围扫描。

其次,当您优化内容时,SELECT * 被认为是有害的。相反,如果您可以只给出所需列的名称,事情会更快。数据库服务器必须传送您请求的所有数据;它无法判断您是否要忽略其中的一些内容。

第三,Timecards (DateIn, Status, ID) 上的复合索引将有助于此查询。该复合索引可用于完成满足查询条件的繁重工作。

这就是所谓的覆盖索引;它包含满足大部分查询所需的数据。如果您只索引 DateIn 列,那么查询处理程序将不得不返回主 table 以找到 StatusID 的值。当这些列出现在索引中时,它会节省额外的操作。

如果您 SELECT 一组特定的列而不是 SELECT *,将这些列包含在覆盖索引中可以显着提高查询性能。这是 SELECT * 被认为有害的几个原因之一。

(有些品牌和型号的 DBMS 有办法指定列的列表以在索引上运行而不实际索引它们。MySQL 要求您索引它们。但是覆盖索引仍然有帮助。)

读这个:http://use-the-index-luke.com/