日期范围在 WHERE 的 ORDER BY 的 MySQL 索引

Posted

技术标签:

【中文标题】日期范围在 WHERE 的 ORDER BY 的 MySQL 索引【英文标题】:MySQL Index for ORDER BY with Date Range in WHERE 【发布时间】:2015-03-10 21:38:40 【问题描述】:

假设您有一个包含以下列的表格:

id
date
col1

我希望能够使用特定的 id 和日期查询此表,并按另一列排序。例如,

SELECT * FROM TABLE WHERE id = ? AND date > ? ORDER BY col1 DESC

根据this 范围文档,索引在遇到> 运算符后将停止使用。但是根据this order by 文档,如果索引按索引中的最后一列排序,则只能使用索引来优化 order by 子句。是否可以对该查询的每个部分进行索引查找,或者您只能获得 3 个中的 2 个?我能比index (id, date)做得更好吗?

【问题讨论】:

【参考方案1】:

计划 A:INDEX(id, date)——如果过滤掉很多行,效果最好,使后续的“文件排序”成本不高。

Plan B:INDEX(col1),如果 WHERE 子句过滤的行很少,这可能效果最好。这避免了文件排序,但不一定比这里的其他选择快。

Plan C: INDEX(id, date, col1) -- 这是一个“覆盖”索引如果查询不引用任何其他字段。这里的潜在优势是只查看索引,而不必接触数据。如果适用的话,Plan C 比 Plan A 更好。

您没有提供足够的信息来说明哪些 INDEX 最有效。如果“覆盖”适用,建议添加 C 和 B;否则添加 A 和 B。查看优化器选择的索引。 (优化器仍有可能不会选择“正确”。)

(这三个索引是我Index blog推荐的。)

【讨论】:

您的算法很有帮助。但是我对mysql Documentation 的印象是,由于 where 子句中的> 条件,即使是“覆盖”索引 (C) 也会在 date 停止索引。我错了吗?就我而言,这并不重要,因为我选择了大约 15 列以上。我简化了问题的问题,但仍然很高兴知道。 如果您选择 15 列,请不要创建覆盖索引。是的,由于范围条件,将停止使用索引进行过滤或排序。它将 (1) 过滤 WHERE,然后从索引中收集 only 所需的其余内容,并对其进行排序。保存的内容不必在索引(一个 BTree)和数据(单独存储)之间反弹。

以上是关于日期范围在 WHERE 的 ORDER BY 的 MySQL 索引的主要内容,如果未能解决你的问题,请参考以下文章

SQL:ORDER BY、AND、WHERE 返回布尔错误 [关闭]

第二章:oracle_sql语句之限制(where子句)和排列数据(order by子句)

sql里 where和order by一起使用是怎样的顺序

group by having where order by

sql语句select group by order by where一般先后顺序

sql语句select group by order by where一般先后顺序