使用多列策略反转键索引

Reverse key indexes with multiple columns strategy

提问人:user3016959 提问时间:11/15/2023 最后编辑:user3016959 更新时间:11/16/2023 访问量:31

问:

我正在分区表上创建本地索引,表已分区 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

Oracle 索引 反向 数据库分区

评论

0赞 Jon Heller 11/16/2023
您使用的是哪个版本的 Oracle?如果您使用的是 18c 或更高版本,则此问题可能是一个无关紧要的 XY 问题。如果你遇到热块,那么,正如 BobC 所提到的,可伸缩序列是比反向索引更好的解决方案。当热块出现在同一个会话中时,它们很好,只有当它们发生在并发会话中时才很糟糕,这正是可扩展序列划分工作负载的方式。

答:

1赞 Paul W 11/15/2023 #1

反向索引反转每个列值的字节顺序。它们不会颠倒索引中列的顺序。因此,反向索引将存储:

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),但不适用于日期、反映数量的数字、可能模式匹配的字符串等。通过对唯一列上的表进行哈希分区并使索引成为本地索引,可以实现相同的好处。这也将把插入分散到许多索引块中,同时仍然保留进行不等式搜索的能力。但是,除非热块争用确实是一个问题,否则不应使用这两种方法。><BETWEENLIKE

1赞 BobC 11/16/2023 #2

除了上面 Paul 的回答之外,如果您使用反向键索引来缓解热块问题,则必须小心,不要只是将热块内存问题更改为冷块物理 IO 问题。如果索引块不全部在缓冲区缓存中,则可能会发生这种情况(我已经见过几次了)。请记住,通过使用反向键索引,您可以将索引分散到更多块中。 解决单调递增索引问题的另一种可能解决方案是使用可缩放序列