MySQL快速查询两个不同的索引,但组合成一个查询速度很慢.为什么?

Ste*_*one 5 mysql performance

我有一张200万行的表.我有两个索引(状态,性别)和(生日).

我觉得很奇怪,这个查询需要3.6秒或更长时间查询N°1

SELECT COUNT(*) FROM ts_user_core
WHERE birthday BETWEEN '1980-01-01' AND '1985-01-01'
    AND status='ok' AND gender='female';
Run Code Online (Sandbox Code Playgroud)

同样的:QUERY N°2

SELECT COUNT(*) FROM ts_user_core
WHERE status='ok' AND gender='female'
    AND birthday between '1980-01-01' AND '1985-01-01';
Run Code Online (Sandbox Code Playgroud)

虽然此查询需要0.140秒QUERY N°3

select count(*) from ts_user_core where (birthday between '1990-01-01' and '2000-01-01');
Run Code Online (Sandbox Code Playgroud)

此查询也需要0.2秒QUERY N°4

select count(*) from ts_user_core where status='ok' and gender='female'
Run Code Online (Sandbox Code Playgroud)

我希望第一个查询更快,这种行为怎么可能?我无法处理这个查询这么多时间.

这里的结果是: 在此输入图像描述

我知道我可以添加一个包含3列的新索引,但有没有办法在不为每个where子句添加索引的情况下获得更快的查询?

谢谢你的建议

Ric*_*mes 3

有没有一种方法可以优化查询,而无需为每个可能的 where 子句添加索引?

是的,有一点。但这需要了解索引的工作原理。

让我们看看SELECTs您到目前为止所展示的所有内容。

  1. 要为 a 构建最佳索引,请从子句中的SELECT所有项目开始。以任意顺序将这些列放入索引中。这给了我们或,但它们之间还没有任何决定。= constantWHEREINDEX(status, gender, ...)INDEX(gender, status, ...)
  2. 添加一个范围或所有ORDER BY. 在你的前几个中SELECTs,那就是birthday。现在我们有INDEX(status, gender, birthday)INDEX(gender, status, birthday)。对于前两者来说,其中任何一个都是“最好的” SELECTs

select count(*) from ts_user_core where status='ok' and gender='female'这些索引对于 #4:也非常有效。所以不需要额外的索引。

现在,我们来讨论#3: select count(*) from ts_user_core where (birthday between '1990-01-01' and '2000-01-01');

  • 它无法使用我们迄今为止拥有的索引。
  • INDEX(birthday)本质上是唯一的选择。

现在,假设我们也有... WHERE status='foo';(没有gender)。这将迫使我们选择INDEX(status, gender, birthday)它的变体而不是它的变体。

结果:2 个良好的索引可以处理所有 5 个选择:

INDEX(status, gender, birthday)
INDEX(birthday)
Run Code Online (Sandbox Code Playgroud)

建议:如果您最终得到的列数超过 5INDEXes或索引的列数超过 5,那么缩短一些索引可能是明智之举。这就是事情变得非常模糊的地方。如果您想向我提供十几个“现实”索引,我将引导您完成它。

其他评论的注释:

  • 对于计时,每个查询运行两次并执行第二次——以避免缓存影响。(你的3.6vs0.140闻起来像是索引的缓存。)
  • 对于计时,请关闭查询缓存或使用SQL_NO_CACHE.
  • 优化器很少在单个查询中使用两个索引。
  • 向我们展示EXPLAIN平原;我们可以帮助您阅读。
  • 在多个索引中进行选择所花费的额外时间通常是值得的。
  • 如果有INDEX(a,b,c),则不需要INDEX(a,b)