MySQL复合索引和运算符BETWEEN

时间:2010-12-03 16:58:22

标签: sql mysql composite indexing between

我对此查询有疑问:

SELECT * 
  FROM runs 
 WHERE (NOW() BETWEEN began_at 
                  AND finished_at)

您认为为beginning_at和finished_at列创建复合索引是否有意义? 或者仅为begin_at?

创建索引是有意义的

6 个答案:

答案 0 :(得分:7)

你的风格非常罕见。

大多数人可能会写WHERE began_at < NOW() AND finished_at > NOW()

然而。我建议在这两个字段上添加一个索引。

组合键不会对您有用,因为它只会加快搜索者的特定日期组合。

嗯,这并不完全正确,因为如果你使用betree,组合键会帮助你,但不会像单独索引它们一样好。 如果使用等号(=)运算符搜索字段组合,则组合键非常好。单元字段索引在ragen请求中表现更好。

你可以谷歌搜索一下“多维范围搜索”。

原因是一个字段中的所有匹配字段基本上可以在btree中的log(n)时间中找到。 因此,您的整体运行时间将为O(k * log(n)),即O(log(n))。

多维范围查询的运行时间O(sqrt(n))更高。然而,也有更好的实现,也是acheav对数运行时。 但是它们并没有在mysql中完全实现,因此根据版本的不同,它会更糟或更糟糕。

所以让我总结一下:

  • 单个字段的等式比较:哈希索引(运行时O(1))

  • 单个字段的范围搜索:单个字段的btree索引(O(log(n)))

  • 多个字段的平等搜索:组合哈希键(运行时O(1))

那些案件是明确的......

  • 多个字段的范围搜索:单独的btree索引(O(log(n)))

这是不太清楚的地方。由于上面给出的原因,对于当前版本,它明显更好地单独索引。 通过对该用例的完美实现,您可以使用组合键获得更好的性能,但是没有系统知道它支持它。 从版本5.0开始,mysql支持松散索引(你需要它),但只是非常有限,而查询优化器仅在极少数情况下才使用它们。不知道5.3等新版本。

但是,如果使用mysql实现松散索引,那么在您执行范围请求或在不同方向上排序的字段上组合键变得越来越相关。

答案 1 :(得分:1)

由于使用不等式而不是等式,复合索引不会比两个单独的索引做得更好(如果不是更糟)。

我主张在began_atfinished_at上倾向于两个单独的索引。

松散索引扫描的参考:

http://www.mysqlperformanceblog.com/2006/05/09/descending-indexing-and-loose-index-scan/

http://dev.mysql.com/doc/refman/5.5/en/loose-index-scan.html

答案 2 :(得分:1)

“索引合并”策略可以从MySQL 5开始发挥作用:http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html - 这也表明单独的索引可能更好。

但是,我从来没有能够让它为我工作:)

答案 3 :(得分:0)

这类问题的正确答案总是:“它取决于”。尝试两种方式和基准测试并比较执行计划。请注意,答案也会随着表中数据量的变化和查询工作负载的变化而变化。一个不断发展的系统的索引几乎不会被发射并忘记。

答案 4 :(得分:0)

很好的问题,但我实际上是从 began_atfinished_at上的索引开始的,因为你可以改写这个查询的一种合理方式是这样的

SELECT *
  FROM runs
 WHERE began_at < NOW()
   AND finished_at > NOW()

这让我更清楚(对我而言)每列需要自己的索引。

答案 5 :(得分:0)

在尝试优化此类查询时,我从未让MySQL使用begin_atfinished_at两个单独的索引。显然,其他人都说复合索引也不起作用,因此可能无法让MySQL使用索引优化此查询。