【问题标题】:Why does order of where clauses effecting the performance?为什么 where 子句的顺序会影响性能?
【发布时间】:2016-12-28 07:04:28
【问题描述】:

我对 where 子句的排序有疑问。

我从其他问题中看到 where 子句的顺序不会影响 sql 查询的性能,但是我的查询性能会随着我更改顺序而改变。

select sql_no_cache idx
from rr
where (timestamp >= '2016-11-28' and timestamp <= '2016-12-28')
  and ((select name from xx where midx=rr.midx) like 'test'

select sql_no_cache idx
from rr
where ((select name from xx where midx=rr.midx) like 'test'
  and (timestamp >= '2016-11-28' and timestamp <= '2016-12-28')

表 rr 在 'idx'、'midx' 和 'timestamp' 上有索引

知道为什么吗??

【问题讨论】:

  • 因为查询优化器并不完美。

标签: mysql query-optimization


【解决方案1】:

如果所有信息都可用,优化器将查看WHERE 的所有部分,然后决定首先执行哪些部分。当顺序在语义上不相关时,顺序将被忽略。

一个规则,实际上是为了优化,是 MATCH...AGAINST 将首先执行。

但是,在某些情况下(例如您的情况),优化器不知道哪个部分会更好。因此,它重新寄希望于用户最了解;短路可能会对性能产生巨大影响。

括号不控制顺序,只控制语义。 (通常它们只是多余的。)

(select name from xx where midx=rr.midx) like 'test' 可以转换为 EXISTS (SELECT * FROM xx WHERE midx=rr.midx AND name = 'test') -- 优化器确实理解 EXISTS(...) 并且比您的公式做得更好。

"table rr 在 'idx'、'midx' 和 'timestamp' 上有索引" -- 不明确。那是三个 1 列索引吗?还是一个 3 列的综合索引? (有一个很大的差异。)这些都是可取的:

rr:  INDEX(timestamp)
xx:  INDEX(midx, name)

【讨论】:

  • 很好的答案!我将尝试使用 EXISTS。谢谢!
  • 我建议使用 IN 而不是 EXISTS,因为这样优化器可能会选择进行 SEMIJOIN 转换,并将子查询转换为连接。换句话说,类似于:“SELECT idx FROM rr WHERE timestamp BETWEEN '2016-11-28' AND '2016-12-28' AND midx IN (SELECT midx FROM xx WHERE name = 'test')。索引建议瑞克还是有用的。
  • 半连接优化直到 5.6.10(或者可能更高版本)才添加。 @nolsigan - 你用的是什么版本?
  • mysql 版本为 5.6.28。所以看来用IN是个不错的选择。:D
【解决方案2】:

我的猜测是短路造成的,基本上sub select只有在时间戳条件为真时才会执行。

当大多数行的时间戳条件为真时,您可能会得到相同的性能结果。

This SO has some info on this.

And also this one, marked as duplicate as the former.

【讨论】:

  • 感谢您的回答。你能更具体地解释一下吗?我知道只有在第一个查询的时间戳条件为真时才会执行子选择,但为什么不为第二个查询呢?优化器不应该选择在时间戳上运行索引扫描而不考虑子句顺序吗?
  • “为什么”是一个哲学问题。你遇到的问题真的是哲学问题吗?
  • 嗯.. 我不这么认为。我只是想确定每次尝试编写 sql 查询时是否必须考虑 where 子句排序,或者只是相信优化器会为我完成这项工作。
  • 我不是这方面的专家,所以我将回答另一个问题:优化器如何知道第一个条件优于第二个?
  • 据我所知,括号会强制执行某种顺序,根据我的经验,短路确实会影响评估顺序,但就像我说的那样,我对此没有权威。
猜你喜欢
  • 2011-05-01
  • 2017-03-22
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多