ORDER BY 优化是不是在以下 SELECT 语句中生效?

Posted

技术标签:

【中文标题】ORDER BY 优化是不是在以下 SELECT 语句中生效?【英文标题】:Does the ORDER BY optimization takes effect in the following SELECT statement?ORDER BY 优化是否在以下 SELECT 语句中生效? 【发布时间】:2012-01-26 07:22:10 【问题描述】:

我有一个想要优化的SELECT 语句。 mysql - order by optimization 表示在某些情况下索引不能用于优化ORDER BY。具体点:

您对键的非连续部分使用 ORDER BY SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;

让我想,这可能是这样的。我正在使用以下索引:

UNIQUE KEY `met_value_index1` (`RTU_NB`,`DATETIME`,`MP_NB`),
KEY `met_value_index` (`DATETIME`,`RTU_NB`)

使用以下 SQL 语句:

SELECT * FROM met_value
WHERE rtu_nb=constant
AND mp_nb=constant
AND datetime BETWEEN constant AND constant
ORDER BY mp_nb, datetime
删除索引met_value_index1 并使用新的排序RTU_NBMP_NBDATETIME 创建它是否足够? 是否必须将 RTU_NB 包含在 ORDER BY 子句中?


结果:我尝试了@meriton 的建议并添加了索引met_value_index2SELECT 在 1.2 秒后完成,之前它在 5.06 秒后完成。以下不属于问题,但作为附注:经过其他一些尝试后,我将引擎从 MyISAM 切换到 InnoDB - 使用 rtu_nb, mp_nb, datetime 作为主键 - 语句在 0.13 秒后完成!

【问题讨论】:

【参考方案1】:

出现在 WHERE 子句中的字段顺序必须与索引中的顺序相匹配。因此,对于您当前的查询,您需要一个包含按 rtu_nb、mp_nb、日期时间顺序排列的字段的索引。

【讨论】:

This is not true,也与问题无关。 在 MySQL 中,这是绝对正确的。对于 innodb 引擎索引尤其如此。查看优点的答案或阅读 Zawodnys 关于此事的教科书。【参考方案2】:

我认为它不会为 ORDER BY 使用任何索引。但是你应该看看execution plan。或here。

【讨论】:

【参考方案3】:

我没有收到您的询问。如果一行必须匹配mp_np = constant 才能返回,则所有返回的行都将具有相同的mp_nb,因此在order by 子句中包含mp_nb 无效。我建议你使用语义等价的语句:

SELECT * FROM met_value
WHERE rtu_nb=constant
AND mp_nb=constant
AND datetime BETWEEN constant AND constant
ORDER BY datetime

避免不必要地混淆查询优化器。

现在,对于您的问题:如果数据库知道底层访问将以正确的顺序返回行,则它可以在不排序的情况下实现 order by 子句。在索引的情况下,这意味着如果 where 子句匹配的行按照 order by 子句请求的顺序出现在索引中,则索引可以帮助排序。

这里就是这种情况,所以数据库实际上可以在met_value_index1 上对rtu_nb=constant AND datetime BETWEEN constant AND constant 所在的行进行索引范围扫描,然后检查每一行是否有mp_nb=constant,但这相当于检查如果mp_nb=constant 具有高选择性,则行数远远超过必要的行数。换句话说,如果匹配的行在索引中是连续的,则索引最有用,因为这意味着索引范围扫描只会触及实际需要返回的行。

因此,以下索引对此查询更有帮助:

UNIQUE KEY `met_value_index2` (`RTU_NB`,`MP_NB`, `DATETIME`),

因为所有匹配的行将在索引中彼此相邻,并且这些行按照order by 子句请求的顺序出现在索引中。我不能说查询优化器是否足够聪明,所以你应该检查执行计划。

【讨论】:

感谢您的解释和建议。我会尝试并尽快报告结果-目前远程机器已断电-我很好奇,会发生什么变化。

以上是关于ORDER BY 优化是不是在以下 SELECT 语句中生效?的主要内容,如果未能解决你的问题,请参考以下文章

ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 是不是保留订单?

MySQL ORDER BY CASE 优化

Mysql group by,order by,dinstict优化

SQL 查询 MATCH 与别名和 order by 并优化查询

order by limit 造成优化器选择索引错误

oracle order by 优化(小白一个,球不鄙视)