ORDER BY A*B 的 MySQL 索引

Posted

技术标签:

【中文标题】ORDER BY A*B 的 MySQL 索引【英文标题】:MySQL index for ORDER BY A*B 【发布时间】:2014-08-10 09:09:45 【问题描述】:

我有一个 mysql InnoDB 表,其中包含两个 INT 列,例如 col1col2。我想添加一个索引,让我能够: SELECT * from myTable WHERE col0=5 ORDER BY col1*col2 DESC 是否有可能有一个支持这种排序的索引,或者我需要添加一个保留该值的列(col1*col2)?

【问题讨论】:

我不这么认为。索引只是列,不用于存储表达式。 你为什么需要一个索引? 如果col0 上有索引,则可能会使用 WHERE 子句中的索引。如果查询没有返回太多匹配项,a*b 排序不会受到影响。 @Strawberry @Jonny 你说得对,如果WHERE 没有返回太多匹配项,排序不会受到影响,但它确实(在 C*100k 范围内)跨度> 诺姆,见ORDER BY Optimization。如果有使用key1 的WHERE 子句,key2 可能不能用于排序。只有key1 或最终key1 的一部分。也许可行,将col1*col2 放在另一列中,但将一个索引放在col0order_col 上。检查 EXPLAIN SELECT... 【参考方案1】:

诺姆,见ORDER BY Optimization‌​。如果要使用索引进行排序,它应该与索引相同,即在 WHERE 子句中使用,当然排序值需要存储在它自己的列中。 Here I generated a test table with 100k rows,应该符合你的情况。


1.) 在两列上添加 ONE INDEX(这适用于使用索引进行选择和排序):

ALTER TABLE `test_data` ADD INDEX super_sort (`col0`,`sort_col`);
EXPLAIN SELECT * FROM `test_data` WHERE col0 = 50 ORDER BY sort_col;

key -> super_sort;额外 -> 使用 where (索引用于 WHERE 和 SORT)


2.) 添加两个索引,一个用于 WHERE,一个用于 SORT(不起作用)

ALTER TABLE `test_data` DROP INDEX `super_sort`;
ALTER TABLE `test_data` ADD INDEX (`col0`);
ALTER TABLE `test_data` ADD INDEX (`sort_col`);
EXPLAIN SELECT * FROM `test_data` WHERE col0 = 50 ORDER BY sort_col;

键-> col0;额外 -> 使用 where;使用文件排序 (索引用于 WHERE,但不用于排序)


所以答案是:是的,您需要一列来保持该值 (col1*col2) 并且您需要在两列上都有一个索引:col0(用于 WHERE 子句)+ sort_col(用于排序)就像第一个例子一样。只要您ORDER BY 进行任何计算(例如col1*col2),就没有索引可用于排序。

【讨论】:

【参考方案2】:

您可以添加包含col1*col2 值的新列并将其用于排序。否则你可以使用SELECT * from myTable WHERE col0=5 ORDER BY col1*col2 DESC

【讨论】:

那一栏的原因是什么? 我的意思是两种方法都可以,但是在从数千行读取数据时保留新列会使其更快,并且在使用新列存储数据时会出现存储问题。 你仍然没有解释为什么你的答案是正确的;问题本身表明这是可能的,但问题是询问是否需要这样做,或者是否可以使用某种索引。 不过,你可以介绍一些其他的方法,如果你知道的话,那会更快。 如果可能,请使用正确的代码块和语法。

以上是关于ORDER BY A*B 的 MySQL 索引的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL order by排序与索引关系总结

MySQL 原理分析之 Trace 分析 order by 的索引原理

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

MYSQL性能调优05_覆盖索引索引下推如何选择合适的索引Order by与Group by优化索引设计原则

MySQL如何利用索引优化ORDER BY排序语句

MySQL 在 VARCHAR 上引用索引前缀时如何使用 ORDER BY?