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

Posted

技术标签:

【中文标题】Oracle:索引中的列顺序重要吗?【英文标题】:Oracle: does the column order matter in an index? 【发布时间】:2011-01-12 21:07:56 【问题描述】:

可以使用任一语句创建两列的索引

create index foo_ix on foo(a,b);
create index foo_ix on foo(b,a);

    这对使用索引的操作(运行时)特性有何影响?

    这对索引的布局(物理)特性有何影响?

    (1)或(2)是否受列的类型/大小影响?

    创建多列索引的最佳做法是什么?

简而言之,我先放哪一列重要吗?

【问题讨论】:

【参考方案1】:
    如果ab 都有1000 个不同的值并且它们总是一起查询,那么索引中列的顺序并不重要。但是,如果 a 只有 10 个不同的值,或者您的查询只使用其中一列,那么这很重要;在这些情况下,如果列顺序不适合查询,则可能不会使用索引。 具有最少不同值的列应位于第一个,具有最多不同值的列位于最后。这不仅最大限度地提高了索引的效用,还增加了索引压缩的潜在收益。 列的数据类型和长度会影响我们从索引压缩中获得的回报,但不会影响索引中列的最佳顺序。 首先排列选择最少的列,最后排列选择最多的列。在与更可能单独使用的列连接的情况下。

2. 和 3. 的一个潜在例外是 DATE 列。因为 Oracle DATE 列包含一个时间元素,它们每天可能有 86400 个不同的值。然而,对数据列的大多数查询通常只对 day 元素感兴趣,因此您可能只想在计算中考虑不同天数。虽然我怀疑它不会影响少数情况下的相对选择性。

编辑(回应 Nick Pierpoint 的评论)

选择最少的列领先的两个主要原因是

    索引压缩 索引跳过读取

知道当前槽中的值与前一个槽中的值相同,这两种方法都发挥了作用。因此,我们可以通过最小化值变化的次数来最大化这些技术的回报。在以下示例中,A 有四个不同的值,B 有六个。同上表示可压缩的值或可跳过的索引块。

Least selective column leads ...

A          B
---------  -
AARDVARK   1
"          2
"          3
"          4
"          5
"          6
DIFFVAL    1
"          2
"          3
"          4
"          5
"          6
OTHERVAL   1
"          2
"          3
"          4
"          5
"          6
WHATEVER   1
"          2
"          3
"          4
"          5
"          6

最具选择性的列前导...

B  A
-  --------
1  AARDVARK
"  DIFFVAL
"  OTHERVAL
"  WHATEVER
2  AARDVARK
"  DIFFVAL
"  OTHERVAL
"  WHATEVER
3  AARDVARK
"  DIFFVAL
"  OTHERVAL
"  WHATEVER
4  AARDVARK
"  DIFFVAL
"  OTHERVAL
"  WHATEVER
5  AARDVARK
"  DIFFVAL
"  OTHERVAL
"  WHATEVER
6  AARDVARK
"  DIFFVAL
"  OTHERVAL
"  WHATEVER

即使在这个简单的示例中,(A, B) 也有 20 个可跳过的插槽,而 (B, A) 有 18 个。更大的差异将在索引压缩上产生更大的 ROI,或者从索引跳过读取中产生更好的效用。

与大多数调整启发式方法一样,我们需要使用实际值和实际数量进行基准测试。这绝对是一种数据倾斜可能对不同方法的有效性产生巨大影响的情况。


“我认为如果你有一个高度选择性的第一个索引,那么 - 从一个 性能观点 - 你最好把它放在第一位。”

如果我们有一个高度选择性的列,那么我们应该为它建立一个自己的索引。避免对少数行执行 FILTER 操作的额外好处不太可能被维护复合索引的开销所抵消。

多列索引在我们有以下情况时最有用:

两列或多列中等选择性, 在同一查询中经常使用。

【讨论】:

嗨。我不清楚你的第 4 点。你能解释一下吗?一般来说,我会将选择性列放在首位。当我认为直方图可能有用地引导 CBO 完全跳过索引时,我只会将选择性最少的列放在首位。 感谢 APC 的额外编辑 - 清楚地表明了你的观点。您对当时需要进行基准测试的评论做得很好。我认为如果你有一个高度选择性的第一个索引——从性能的角度来看——你最好把它放在第一位。基准...基准...基准...【参考方案2】:

但是按照Oracle自己的说法,最好把基数最高的列放在前面:

http://docs.oracle.com/cd/B10500_01/server.920/a96533/data_acc.htm#2174

复合索引的排序键

如果在 WHERE 子句中使用所有键的频率相同,那么在 CREATE INDEX 语句中将这些键从选择性最高到选择性最低的顺序排列可以最好地提高查询性能。

【讨论】:

查看为较新的 Oracle 版本编写的文档:docs.oracle.com/cd/E25178_01/server.1111/e16638/… 您引用的要点在较新的版本中不存在(我链接了 11g),可能是因为出现了 Index Skip Scan。跨度> 【参考方案3】:

您可以在这里找到一些问题的答案:Index Skip Scan – Does Index Column Order Matter Any More? (Warning Sign)

【讨论】:

像往常一样,答案是“视情况而定”:取决于使用 Oracle9i+ 还是旧版本;关于列的基数和索引表的典型使用场景。【参考方案4】:
    如果列单独使用 查询 Oracle 将使用更少 高效的跳过扫描索引访问 路径,如果它不是前导列 在索引中 取决于 各自的选择性 列 没有 我会查看涉及索引中列的查询,并按查询次数最多的方式对它们在索引中的位置进行排名

【讨论】:

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

多列索引列顺序

相同列上的 Oracle 2 索引但顺序不同

Oracle SQL 语句中的条件顺序是不是重要?

列顺序很重要的 Oracle DB 简单 SELECT

Oracle索引聚簇因子的含义及重要性

列存储索引中列的顺序在 SQL Server 2012 中是不是重要