多列索引列顺序

Posted

技术标签:

【中文标题】多列索引列顺序【英文标题】:multicolumn index column order 【发布时间】:2011-05-14 20:15:52 【问题描述】:

我被告知并在各处阅读它(但没有人敢解释原因),在多列上编写索引时,出于性能原因,我应该将最具选择性的列放在首位。 这是为什么? 是神话吗?

【问题讨论】:

哇,这么多问题我没有回答 【参考方案1】:

我应该把最有选择性的列放在第一位

According to Tom,列选择性对于使用索引中所有列的查询没有性能影响(它确实会影响 Oracle 压缩索引的能力)。

这不是第一件事,也不是最重要的事情。当然,这是值得考虑的事情,但在宏伟的计划中相对较远。

在某些奇怪的、非常奇特的和异常的情况下(比如上面的数据完全歪斜),选择性很容易很重要,但是,它们是

a) 非常罕见 b) 真正依赖于运行时使用的值,因为所有倾斜查询都是

所以一般来说,看看你有什么问题,试着在此基础上尽量减少你需要的索引。

在考虑时,连接索引中的列中不同值的数量不相关 索引中的位置。

但是,在决定索引列的顺序时,这些考虑应该排在第二位。更重要的是要确保索引对许多查询有用,因此列顺序必须反映查询的 where 子句中这些列的使用(或缺少这些列)(出于 AndreKR 说明的原因)。

你如何使用索引——这是决定时的相关因素。

在所有其他条件相同的情况下,我仍然会将最具选择性的列放在首位。感觉刚刚好……

更新: Another quote from Tom(感谢 milan 找到它)。

在 Oracle 5(是的,版本 5!)中,有一个论点是将最有选择性的列放在首位 在索引中。

从那时起,将最有区别的条目放在索引中的第一位是不正确的 将使索引更小或更高效。好像会,但不会。

带索引 密钥压缩,有一个令人信服的论据可以采用另一种方式,因为它可以使索引 更小。但是,如前所述,它应该由您使用索引的方式决定。

【讨论】:

您将索引压缩信息作为附注,但不应忽略它。在很多情况下,压缩索引是一个绝妙的主意。 @Craig:我可以看到列排序如何影响索引压缩,但反过来会不会起作用(低基数的前导列导致重复的、可压缩的前缀)?跨度> Tom 说对于 Oracle 5 asktom.oracle.com/pls/asktom/…【参考方案2】:

使用索引时可以从右到左省略列,即当您在col_a, col_b 上有索引时,您可以在WHERE col_a = x 中使用它,但不能在WHERE col_b = x 中使用它。

想象有一个电话簿,它按名字排序然后按姓氏排序。

至少在欧洲和美国,名字的选择性远低于姓氏,因此查找名字不会缩小结果集的范围,因此仍有很多页面需要检查正确的姓氏。

【讨论】:

+1。如果前导列丢失,您仍然可以使用索引,但这将是全索引扫描(或索引跳过扫描),效率并不高(但仍可能比全表扫描更好)。跨度> 不过,这并没有回答关于选择性的部分。 我认为至少在欧洲和美国,名字的选择性比姓氏的选择性低得多,所以按名字在前的索引不会有太大帮助。 AndrewKR,是的,但这取决于在最左边指定最多选择列的索引。如果您将其添加到您的答案中,我会给您 +1。 @PerformanceDBA 我不太明白你的意思。你能详细说明一下吗?【参考方案3】:

索引中列的顺序应由您的查询决定,而不是任何选择性考虑因素。如果你在 (a,b,c) 上有一个索引,并且你的单列查询大部分都是针对 c 列,然后是 a,那么在索引定义中按照 c,a,b 的顺序放置它们以获得最佳效率. Oracle 更喜欢使用索引的前沿进行查询,但可以在效率较低的访问路径(称为跳过扫描)中使用索引中的其他列。

【讨论】:

【参考方案4】:

您的索引越有选择性,研究就越快。

想象一下电话簿:您可以通过姓氏快速找到某人。但是,如果您有很多人的姓氏相同,那么您将持续更多的时间通过每次查看名字来寻找该人。

所以你必须首先给出最具选择性的列,以尽可能避免这个问题。

此外,您应该确保您的查询正确使用了这些“选择性标准”。

【讨论】:

+1。这是完全正确的。假设已经完成,(AndrewKR) 列可以从右向左删除。

以上是关于多列索引列顺序的主要内容,如果未能解决你的问题,请参考以下文章

多列 BRIN 列顺序是不是重要?

Oracle:索引中的列顺序重要吗?

MySQL中多列索引的字段顺序是不是重要

具有列顺序的响应式多列列表

Hibernate - 具有排序顺序的多列索引

数据库索引