我很难弄清楚,所以让我问你。给出以下查询:
select name from users where company_id = ? and creation_date > ?
比方说,我们只有2家公司,每家公司在不同时刻创建的数百万用户。因此creation_date
的基数要高得多。以下哪个索引速度更快,为什么?
哪个索引更快(或理论上相等)?忽略磁盘空间使用,除非以某种方式影响读取性能。我的想法:
(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?
答案 0 :(得分:2)
对于该特定查询,index_a应该是最快的,因为结果恰好对应于索引中的范围。
使用index_b或index_c较慢。您必须获取有效日期范围,然后过滤出带有错误公司ID的行。在这两个索引中,index_c较慢,因为您必须触摸过滤出的行。
使用index_d最慢。您可以找到公司ID的范围,但是必须扫描所有行以查找匹配的日期。