MySQL Btrees:使用所有列时,基数和列顺序对复合索引是否重要?

时间:2018-07-05 23:10:33

标签: mysql database algorithm indexing b-tree

我很难弄清楚,所以让我问你。给出以下查询:

select name from users where company_id = ? and creation_date > ?

比方说,我们只有2家公司,每家公司在不同时刻创建的数百万用户。因此creation_date的基数要高得多。以下哪个索引速度更快,为什么?

  1. index_a(company_id,creation_date)
  2. index_b(创建日期,company_id)
  3. index_c(creation_date)
  4. index_d(company_id)

哪个索引更快(或理论上相等)?忽略磁盘空间使用,除非以某种方式影响读取性能。我的想法:

(index_b ~= index_c) > index_a > index_d因为在Btree中“时间戳记”将被分组在单个区域中,所以提取将更早地停止。 company_id实际上并不重要,因为它需要使用索引中的ROWID来触摸表行以获取name的{​​{1}}数据库。几乎没有区别。第二名是SELECT,它在BTREE中将低基数值“分组”在一起,因此通过限制index_a的搜索范围,“ b-搜索”显示其值需要花费一些时间。 (位于索引的“尾部”)。最后,creation_date由于明显的原因(在一百万行的示例中为2的基数)而变得更糟。

Bônus问题:如果我们有10kk行,A公司和B公司有5kk行,而两个公司的7kk时间戳均匀分布,而其他3kk时间戳却完全不同,该怎么办? 7kk范围内的搜索会比3kk范围内的搜索差很多吗?

是吗?我想念什么?

(可视化算法的好地方:https://www.cs.usfca.edu/~galles/visualization/BTree.html

PS: StackOverflow中有两个相互矛盾的答案:

performant ordering of keys in a MySQL compound index (WRT Rails Polymorphic associations and STI)

For a composite index of columns of different cardinality, does order matter?

1 个答案:

答案 0 :(得分:2)

对于该特定查询,index_a应该是最快的,因为结果恰好对应于索引中的范围。

使用index_b或index_c较慢。您必须获取有效日期范围,然后过滤出带有错误公司ID的行。在这两个索引中,index_c较慢,因为您必须触摸过滤出的行。

使用index_d最慢。您可以找到公司ID的范围,但是必须扫描所有行以查找匹配的日期。