MySQL:为具有多个表达式之间的WHERE子句编制索引

MySQL:为具有多个表达式之间的WHERE子句编制索引,mysql,optimization,indexing,between,Mysql,Optimization,Indexing,Between,在桌子上,例如: 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索引应该可以做到这一点,但解释说并非如此。它说它将使用一个键4来匹配k1,但是在匹配k2时它并没有真正的好处(除了在表中缩小一些范围。但是如果k1的范围很宽,那么对

在桌子上,例如:

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索引应该可以做到这一点,但解释说并非如此。它说它将使用一个键4来匹配k1,但是在匹配k2时它并没有真正的好处(除了在表中缩小一些范围。但是如果k1的范围很宽,那么对k2的约束仍然有很多工作要做)

一篇MySQL Performance博客文章可能指出不应该这样做,因为一旦使用了间隔范围,它就会扫描其余部分:

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

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

这似乎是一种相当普遍的情况,需要建立索引,但我很少看到这样的问题


提前感谢您的帮助

的确,使用标准的B-树搜索,您可以在范围谓词中搜索一列(
介于
之间作为范围谓词,如
!=
in()
类似
,或
为[NOT]NULL

因此,您的列
k1
受益于索引,而第二列实际上无法受益于索引。您可以在EXPLAIN的
key\len
字段中看到此操作的效果。它将只使用部分索引,对应于
k1
数据类型的大小,而不是
k1
k2

MySQL 5.6通过一个名为索引条件下推的新特性改进了优化器。这意味着在索引缩小给定
k1
的搜索范围后,剩余的搜索词将传递给存储引擎,因此至少不需要SQL引擎扫描所有行。存储引擎可以对它们进行预过滤

有关MySQL 5.6中ICP的更多详细信息,请参阅


另请参阅我的演示。

MySQL并不是以查询优化而闻名的,我知道。这就是我试图优化它的原因。:)如果Optimizer认为扫描速度更快,它可以选择使用索引或进行完整扫描。这是根据统计数据进行的。如果您能向我们提供
EXPLAIN
的输出,并使用
INDEX
提示使用您的(k1,k2)索引。