在(a, b)
上创建的非聚集索引是表的一部分“副本”,其行按照a
,然后按照b
排序,并包含对原始行的引用。
它有助于运行以下查询:
SELECT *
FROM mytable
WHERE a = @A
AND b = @B
, this:
SELECT *
FROM mytable
ORDER BY
a, b
, this:
SELECT *
FROM mytable
WHERE a = @A
ORDER BY
b
例如,我们有这样的一个表格:
和许多其他的。
比如说,我们有这样一张表:
1 1 1 1
2 1 4 8
3 7 2 3
4 3 3 9
5 8 9 4
6 2 2 7
7 5 3 5
8 3 9 4
如果我们在
(col2, col3)
上创建索引,它将包含以下数据:
col2 col3
1 1 1
2 3 3
2 7 6
3 5 7
3 9 4
4 8 2
9 4 5
9 4 8
即首先按col2
排序,其次按col3
排序,最后按行引用排序。
很容易看出,这个索引也是col2
的索引(按(col2, col3)
排序意味着仅按col2
排序)。
顺序很重要,因此如果我们在(col3, col2)
上创建索引,则行将以不同的方式排序:
col2 col3
1 1 1
2 3 3
9 4 5
9 4 8
3 5 7
2 7 6
4 8 2
3 9 4
这个索引也是基于col3
的。
如果我们想要在(col2, col3)
范围内查找行,只需从有序数据中取出一个切片:
SELECT col2, col3
FROM mytable
WHERE col2 BETWEEN 2 AND 3
col2 col3 #
1 1 1
2 3 3
2 7 6
3 5 7
3 9 4
4 8 2
9 4 5
9 4 8
很容易看出,我们无法使用此索引在
col3
上获取这个切片,因为
col3
本身并没有排序。
上面提到的“参考”是行的
RID
(指向表空间中的位置的指针),如果表本身未集群化,则为其值;如果表已集群化,则为表的群集键的值。
聚集索引
不会创建值的阴影副本。相反,它重新排列表的行本身。
如果您在上述的
(col2, col3)
上创建一个聚集索引,则只会重新排列表的行:
1 1 1 1
3 7 2 3
6 2 2 7
7 5 3 5
4 3 3 9
2 1 4 8
5 8 9 4
8 3 9 4
因此,集群或非集群是一种存储方法,而不是索引。
在 Oracle 中,这被称为索引组织表(行已排序),而不是堆组织表(行未排序)。