提问人:user3016959 提问时间:11/15/2023 最后编辑:user3016959 更新时间:11/16/2023 访问量:31
使用多列策略反转键索引
Reverse key indexes with multiple columns strategy
问:
我正在分区表上创建本地索引,表已分区 X(列表分区)
表 TEST 如下所示:
X | Y | Z |
---|---|---|
血型 | 24 | 63 |
血型 | 24 | 65 |
光盘 | 24 | 63 |
光盘 | 24 | 65 |
英 孚 | 24 | 63 |
如果我创建索引
在测试 (X,Y,Z) LOCAL 上创建唯一索引TEST_IDX;
我“有效地”存储以下内容
AB2463型
AB2465型
CD2463型
CD2465型
EF2463系列
但是,如果我创建反向键索引,则在使用多个列时如何存储数据?
在测试 (X,Y,Z) REVERSE LOCAL 上创建唯一索引TEST_IDX;
它是否存储为?
3643BA型
5643BA型
3643直流电
5643直流
3643FE型
OR存储为:(我希望是这个)
BA4236型
BA4256型
DC4236型
DC4256系列
FE4236型
实际上,此表还有几列和 100 多百万行:
X 有 50 个不同的值
Y 有 150 个不同的值
Z 具有超过 240000000 个不同的值
我删除并创建了反转键的索引,它似乎有所改进,但我担心分区和扩展它
我们每 30 分钟左右对这个表进行几千次更新,它们很慢(每个执行 0.20 次),并且它们正在使用那个唯一的列
IE:(注意 COL A、B、C 未显示在上面) 更新 TEST 集 A = :1 , B = :2 , C = :3 其中 X = :4 AND Y = :5 AND Z =:6
答:
反向索引反转每个列值的字节顺序。它们不会颠倒索引中列的顺序。因此,反向索引将存储:
BA 42 36
BA 42 56
直流 42 36
直流 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)显然不会反转。列之间的相对顺序没有改变。
反向索引的目的是将插入分散到叶节点上,以便在按顺序插入每个递增的列值时不会出现热右前缘。如果您遇到争用,这有助于减少争用。颠倒列顺序没有任何好处(如果您愿意,可以随时自行对列重新排序)。反向索引的缺点是,由于字节以相反的顺序存储,因此它们只能用于相等谓词,而不能用于不等式,如 、 、 (它可以进行完全扫描,但不能对起始值进行范围扫描/二进制搜索)。这使得它适用于没有顺序含义的标识符(如客户 ID),但不适用于日期、反映数量的数字、可能模式匹配的字符串等。通过对唯一列上的表进行哈希分区并使索引成为本地索引,可以实现相同的好处。这也将把插入分散到许多索引块中,同时仍然保留进行不等式搜索的能力。但是,除非热块争用确实是一个问题,否则不应使用这两种方法。>
<
BETWEEN
LIKE
除了上面 Paul 的回答之外,如果您使用反向键索引来缓解热块问题,则必须小心,不要只是将热块内存问题更改为冷块物理 IO 问题。如果索引块不全部在缓冲区缓存中,则可能会发生这种情况(我已经见过几次了)。请记住,通过使用反向键索引,您可以将索引分散到更多块中。 解决单调递增索引问题的另一种可能解决方案是使用可缩放序列
评论