我正在分区表上创建本地索引,该表已分区 X(列表分区)
表 TEST 如下所示:
X | 是 | Z |
---|---|---|
AB | 24 | 63 |
AB | 24 | 65 |
CD | 24 | 63 |
CD | 24 | 65 |
EF | 24 | 63 |
如果我创建索引
在测试(X,Y,Z)本地创建唯一索引TEST_IDX;
我“有效”存储以下内容
AB2463
AB2465
CD2463
CD2465
EF2463
但是,如果我创建反向键索引,那么使用多列时数据如何存储?
在测试(X,Y,Z)上创建唯一索引 TEST_IDX 反转本地;
是否存储为?
3643BA
5643BA
3643DC
5643DC
3643FE
OR 存储为:(我希望是这个)
BA4236
BA4256
DC4236
DC4256
FE4236
实际上,这个表还有更多的列和数百百万行:
X 有 50 个不同的值
Y 有 150 个不同的值
Z 有超过 240000000 个不同的值
我删除并创建了反转键的索引,看起来似乎有所改进,但我担心分区和扩展它
我们每 30 分钟左右就会对此表进行数千次更新,而且更新速度很慢(每次执行 0.20 次)并且他们正在使用该唯一的列
IE:(注意COL A、B、C未在上面显示) 更新测试集 A = :1 、B = :2 、C = :3 其中 X = :4 AND Y = :5 AND Z =:6
反向索引反转每个列值的字节顺序。它们不会颠倒索引中列的顺序。所以反向索引将存储:
BA 42 36
BA 42 56
DC 42 36
DC 42 56
FE 42 36
(当然是 Oracle 的编码格式。它不将数字存储为小数,因此 24 的倒数不是 42,但我们只是使用小数来说明这一点)
您可以通过块转储来演示这一点。正常索引转储:
row#0[8014] flag: -------, lock: 2, len=18
col 0; len 2; (2): 41 42 -- encodes A, B
col 1; len 2; (2): c1 19 -- encodes the number 24
col 2; len 2; (2): c1 40 -- encodes the number 63
col 3; len 6; (6): 00 75 81 d9 00 00
row#1[7996] flag: -------, lock: 2, len=18
col 0; len 2; (2): 41 42 -- encodes A, B
col 1; len 2; (2): c1 19
col 2; len 2; (2): c1 42
col 3; len 6; (6): 00 75 81 d9 00 01
row#2[7978] flag: -------, lock: 2, len=18
col 0; len 2; (2): 43 44 -- encodes C, D
col 1; len 2; (2): c1 19
col 2; len 2; (2): c1 40
col 3; len 6; (6): 00 75 81 d9 00 02
row#3[7960] flag: -------, lock: 2, len=18
col 0; len 2; (2): 43 44 -- encodes C, D
col 1; len 2; (2): c1 19
col 2; len 2; (2): c1 42
col 3; len 6; (6): 00 75 81 d9 00 03
row#4[7942] flag: -------, lock: 2, len=18
col 0; len 2; (2): 45 46 -- encodes E, F
col 1; len 2; (2): c1 19
col 2; len 2; (2): c1 40
col 3; len 6; (6): 00 75 81 d9 00 04
反向索引转储:
row#0[8014] flag: -------, lock: 0, len=18
col 0; len 2; (2): 42 41 -- encodes B, A
col 1; len 2; (2): 19 c1 -- encodes the number 24 *backwards*
col 2; len 2; (2): 40 c1 -- encodes the number 63 *backwards*
col 3; len 6; (6): 00 75 81 d9 00 00
row#1[7996] flag: -------, lock: 0, len=18
col 0; len 2; (2): 42 41 -- encodes B, A
col 1; len 2; (2): 19 c1
col 2; len 2; (2): 42 c1
col 3; len 6; (6): 00 75 81 d9 00 01
row#2[7978] flag: -------, lock: 0, len=18
col 0; len 2; (2): 44 43 -- encodes D, C
col 1; len 2; (2): 19 c1
col 2; len 2; (2): 40 c1
col 3; len 6; (6): 00 75 81 d9 00 02
row#3[7960] flag: -------, lock: 0, len=18
col 0; len 2; (2): 44 43 -- encodes D, C
col 1; len 2; (2): 19 c1
col 2; len 2; (2): 42 c1
col 3; len 6; (6): 00 75 81 d9 00 03
row#4[7942] flag: -------, lock: 0, len=18
col 0; len 2; (2): 46 45 -- encodes F, E
col 1; len 2; (2): 19 c1
col 2; len 2; (2): 40 c1
col 3; len 6; (6): 00 75 81 d9 00 04
请注意,字符串和数字的字节顺序都已颠倒。然而 Oracle 会存储数据类型,它只是反转字节顺序。唯一的例外是 ROWID 本身(转储中的第 3 列)显然没有反转。列相对于彼此的顺序没有改变。
反向索引的目的是将插入分散到叶节点上,这样当您按顺序插入每个增加的列值时,就不会出现热右前缘。如果您遇到争用,这可以帮助减少争用。反转列顺序没有任何好处(如果您愿意,您可以随时自行重新排序列)。反向索引的缺点是,因为字节以相反的顺序存储,所以它们只能用于相等谓词,不能用于不等式,如
>
、<
、BETWEEN
、LIKE
(它可以做 full) 扫描,但不对起始值进行范围扫描/二分查找)。这使得它适用于没有顺序意义的标识符(例如客户 ID),但不适用于日期、反映数量的数字、可能模式匹配的字符串等。通过对表进行哈希分区可以实现相同的好处。唯一的列并使索引成为本地的。这也将把插入分散到许多索引块中,同时仍然保留进行不等式搜索的能力。然而,除非热块争用实际上是一个问题,否则不应使用这两种方法。