【问题标题】:MySQL Slow SELECT QueryMySQL 慢速 SELECT 查询
【发布时间】:2016-01-10 01:08:46
【问题描述】:

我有一个查询,大致如下:

SELECT * FROM table1
WHERE confirmed = 0
AND resource = 123
AND id IN (
  SELECT id FROM table2 WHERE resource = 123
  AND added > 1440000000
)

运行大约需要 3 分钟,但我不知道为什么。这就是我感到困惑的原因......

SELECT id FROM table2 WHERE resource = 123
AND added > 1440000000

此子查询没有结果。一个都没有。所以,我想如果我这样做:

SELECT * FROM table1
WHERE confirmed = 0
AND resource = 123
AND id IN (
 0
)

运行时间应该差不多。除非它没有 - 它立即按预期返回 0 结果。这是怎么回事?将空查询结果与 0 进行比较有什么不同?

行数也很低。我运行了一个解释,它使用表 1 的已确认键和表 2 中的主键。行数分别为 5500 / 20000。

我们将不胜感激地收到任何想法!谢谢!

【问题讨论】:

  • 因为在您的语句中执行的每一行SELECT。在这里使用JOIN不是更合适吗?如果我错过了,请纠正我。
  • 如果您已经运行了说明,最好将其包含在内。
  • 您确定资源和添加的字段已在您的数据库中编入索引吗?
  • Paul,我认为你是对的 - 尽管结果为 0,但为每一行运行每个子查询可能需要一些时间。我以为优化器会执行一次子查询,将其保存在内存中,然后每次比较结果,但事实并非如此。你觉得这对吗?
  • 感谢 Jacub 和 ITOctopus 的建议。我已经更改了该问题的字段名称等,所以我认为只解释“解释”而不是全部更改会更容易。资源上有索引,并按照建议添加了字段。 :)

标签: mysql performance select indexing


【解决方案1】:

使用显式join,您的查询会运行得更快。如果子查询不返回重复值:

SELECT t1.*
FROM table1 t1 JOIN
     (SELECT id FROM table2 WHERE resource = 123 AND added > 1440000000
     ) t2
     ON t1.id = t2.id
WHERE confirmed = 0 AND resource = 123;

另外,MySQL 通常会更好地优化NOT EXISTS

SELECT t1.*
FROM table1 t1
WHERE confirmed = 0 AND resource = 123 AND
      NOT EXISTS (SELECT 1
                  FROM table2 t2
                  WHERE t2.id = t1.id AND t2.resource = 123 AND t2.added > 1440000000
                 );

使用table2(id, resource, added) 上的索引,此查询将运行得更快。

【讨论】:

  • 感谢 Gordon,这非常有用。我猜虽然子查询没有返回任何结果,但它仍然需要足够长的时间来运行。我会更改我的查询,希望能完成这项工作。
【解决方案2】:

IN ( SELECT ... ) 在 5.6 之前优化得很差。 5.6 更好,但仍然不是很好。

JOIN ( SELECT ... ) 必须首先计算,并且需要一个临时表。所以它不如下面的普通JOIN。

SELECT  *
    FROM  table1 AS t1
    JOIN  table2 AS t2 ON t2.id = t1.id
    WHERE  t1.confirmed = 0
      AND  t1.resource = 123
      AND  t2.resource = 123
      AND  t2.added > 1440000000 

还有

table2:  INDEX(resource, added)
table1:  INDEX(resource, confirmed)

【讨论】:

猜你喜欢
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多