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_NB
、MP_NB
、DATETIME
创建它是否足够?
是否必须将 RTU_NB 包含在 ORDER BY
子句中?
结果:我尝试了@meriton 的建议并添加了索引
met_value_index2
。 SELECT
在 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 group by,order by,dinstict优化