为什么附加的子查询的最小ID会使结果快10倍?

时间:2018-12-21 22:49:37

标签: mysql query-performance

当用于限制id范围的附加子查询的结果比WHERE中相同查询的结果快10倍时,会遇到奇怪的情况。

此查询大约需要10秒:

SELECT COUNT(DISTINCT i.id) AS count FROM
      items i
      INNER JOIN items_keywords ik ON ik.article_id = i.id AND ik.deleted = 0
      INNER JOIN category_keywords catk ON catk.keyword_id = ik.keyword_id
      INNER JOIN category cat ON cat.id = catk.category_id AND cat.customer_id = 968
      WHERE 
         i.deleted = 0 
         AND i.edited = 1 
         AND i.created >= '2018-12-18' 
         AND i.created <= '2018-12-20 23:59:59'

说明:

enter image description here

如果我添加其他where子句来设置最小ID,则最多需要1秒钟:

AND i.id > (SELECT MIN(id) FROM items WHERE created >= '2018-12-01')

说明:

enter image description here

使用子查询设置i.id范围(在主查询中删除了i。,并且没有最小id子句)对它进行了测试,它花费了10秒钟,并且解释与第一个查询相同,除了子查询行和主查询中没有创建的索引

AND i.id IN (SELECT id FROM items WHERE created >= '2018-12-18' AND created <= '2018-12-20 23:59:59') #subquery takes 0,047s

所以我应该更改索引中的某些内容还是将最小ID子查询添加到我的所有查询中,因为这会大大提高? 等待任何建议。

某些规格: 的MySQL:5.6.4
项目表:2200万行
items_keywords:1.2亿行
category_keywords:7000万行

这是我的第一个问题,所以不要怪我,而要教我。

添加:
Here is SHOW CREATE TABLE for these tables

1 个答案:

答案 0 :(得分:0)

快10倍-听起来就像在buffer_pool中缓存的数据和没有缓存的数据之间的差异。您为每个查询两次吗?

请为每个表格提供SHOW CREATE TABLE;可能会发生很多微妙的事情。

此索引可能会诱使它首先使用:

INDEX(deleted, edited,  -- in either order
      created,          -- after those others
      id)               -- last

该索引正在“覆盖”,从而提供了额外的推动力。

当前,优化程序决定从cat.customer_id = 968开始。

如果category_keywords是一个多对多映射表,请参见this以获取一些性能提示。

IN ( SELECT ... )可能会过慢。 EXISTS ( SELECT ... )可能会更快。

如果要将内容移入子查询,请将所有i.测试移入其中。这样,它本质上将类似于EXISTS,并且可以使用PRIMARY KEY(id)作为完美索引。 (不需要额外的索引。)