我对此查询有疑问:
SELECT *
FROM runs
WHERE (NOW() BETWEEN began_at
AND finished_at)
您认为为 begin_at 和 finished_at 列创建复合索引有意义吗?还是只为 begin_at 创建索引有意义?
你的风格很不寻常。
大多数人可能会写WHERE began_at < NOW() AND finished_at > NOW()
然而。我建议在这两个字段上都放置一个索引。
组合键对您没有用处,因为它只会加快特定日期组合的搜索速度。
好吧,这并不完全正确,因为如果您使用 betree 组合键会对您有所帮助,但不如单独索引它们好。如果您使用相等 (=) 运算符搜索字段组合,则组合键非常好。单字段索引在 ragen 请求中表现更好。
您可以搜索一下“多维范围搜索”。
原因是一个字段中的所有匹配字段在btrees中基本上可以在log(n)时间内找到。所以你的整体运行时间将是 O(k*log(n)),即 O(log(n))。
多维范围查询的运行时间为 O(sqrt(n)),后者更高。然而,还有更好的实现也可以实现对数运行时。但是它们并没有在 mysql 中完全实现,因此根据版本的不同,它会变得更糟或更糟糕。
所以让我总结一下:
单个字段的相等比较:哈希索引(运行时 O(1))
单个字段的范围搜索:单个字段上的 btree 索引( O(log(n)) )
多个字段的相等搜索:组合哈希键(运行时 O(1))
那些案子很清楚...
这是不太清楚的地方。由于上述原因,使用当前版本显然更好地单独索引。通过该用例的完美实现,您可以使用组合键获得更好的性能,但没有系统知道哪个支持它。自 5.0 版以来,mysql 支持松散索引(您需要它),但非常有限,查询优化器仅在极少数情况下使用它们 afaik。不知道 5.3 之类的新版本。
然而,随着 mysql 在执行范围请求或在不同方向排序的字段上实现松散索引组合键变得越来越相关。
“索引合并”策略可以从 MySQL 5 开始发挥作用:http: //dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html - 这也表明单独的索引可能会更好.
但是,我从来没有让它为我工作:)
由于使用不等式而不是等式,复合索引不会比两个单独的索引做得更好(如果不是更差)。
began_at
我主张在和上倾向于两个单独的索引finished_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
这类问题的正确答案始终是:“视情况而定”。尝试两种方式并进行基准测试并比较执行计划。请注意,随着表中数据量的变化和查询工作负载的变化,答案也会发生变化。不断发展的系统上的索引几乎永远不会被遗忘。
我从来没有让 MySQL 使用两个单独的索引begin_at
来finished_at
优化这种查询。显然,其他人说复合索引也不起作用,因此可能无法让 MySQL 使用索引来优化此查询。
好问题,但实际上我会从两者 began_at
的索引开始和finished_at
,因为您可能会重写此查询的一种合理方式是这样
SELECT *
FROM runs
WHERE began_at < NOW()
AND finished_at > NOW()
这使得(对我来说)每列都需要自己的索引更加清楚。