2

在一张桌子上,例如:

CREATE TABLE foo (..., k1 INTEGER, k2 INTEGER)

我想索引一个查询,例如:

SELECT * FROM foo WHERE (k1 BETWEEN @a AND @b) AND (k2 BETWEEN @x AND @y)

在我看来,在 (k1, k2) 上创建 BTREE 索引应该可以解决问题,但 EXPLAIN 另有说明。它说它将使用 4 的 key_len 来匹配 k1,但是在匹配 k2 时它并没有真正受益(除了在表格中缩小了一些范围。但如果 k1 的范围很宽,那么还有很多对 k2 进行约束的工作量)。

一篇 MySQL 性能博客文章可能表明不应该这样做,因为一旦使用了间隔范围,它就会扫描其余部分:http ://www.mysqlperformanceblog.com/2009/09/12/3-ways-mysql-使用索引/

是否有任何其他索引方案或多表方案可以使该查询达到最佳状态?

我想在 k1 上使用分区。文档说优化器考虑到了这一点。如果我创建了许多分区,并且数据相当分布,那么如果引擎只需要访问少量分区,那么线性扫描会更好。但是,A)在我的特定 mysql 服务器上未启用分区,我无权更改它,并且 B)我的实际应用程序中实际上有 3 个 BETWEEN 语句。所以分区只会帮助第一个 BETWEEN 表达式还有两个要走。

这似乎是一个相当普遍的情况,会出现并且需要索引,但我还没有看到以这种方式提出的问题。

提前感谢您的帮助!

4

1 回答 1

0

确实,使用标准的 B 树搜索,您可以搜索范围谓词中的列(BETWEEN算作范围谓词,如<, >, !=, IN(),LIKEIS [NOT] NULL)。

所以你的列k1从索引中受益,然后第二列真的不能从索引中受益。key_len您可以在EXPLAIN 字段中看到此效果。它只会使用索引的一部分,对应于k1数据类型的大小,不会同时使用k1and k2

MySQL 5.6 使用称为索引条件下推的新功能改进了优化器。这意味着在索引缩小搜索给定k1之后,剩余的搜索词被传递给存储引擎,因此至少不是所有的行都需要被 SQL 引擎扫描。存储引擎可以对它们进行预过滤。

有关 MySQL 5.6 中 ICP 的更多详细信息,请参阅https://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html

另请参阅我的演示文稿如何设计索引,真的

于 2014-04-24T22:06:16.270 回答