oracle 使用多列策略的反向键索引

qmb5sa22  于 2023-11-17  发布在  Oracle
关注(0)|答案(2)|浏览(129)

我正在创建分区表的本地索引,该表被分区为X(列表分区)
表TEST看起来像这样:
| X| Y| Z|
| --|--|--|
| AB| 24 | 63 |
| AB| 24 | 65 |
| CD| 24 | 63 |
| CD| 24 | 65 |
| EF| 24 | 63 |
如果我创建一个索引
创建唯一索引TEST_IDX ON TEST(X,Y,Z);
我“有效地”存储以下内容
AB2463
AB2465
CD2463
CD2465
EF2463
但是,如果我创建一个反向键索引,当使用多列时,数据是如何存储的?
创建唯一索引TEST_IDX ON TEST(X,Y,Z)REVERSE;
是否存储为?
小行星3643 BA
小行星5643 BA
小行星3643 DC
小行星5643 DC
小行星3643 FE
OR is存储为:(我希望是这个)
BA4236
BA4256
DC4236
DC4256
FE4236
实际上,这个表有几列和数百万行:
X有50个不同的值
Y有150个不同的值
Z有超过240000000个不同的值
我删除并创建了索引,反转了键,似乎有了改进,但我担心分区和扩展
大约每30分钟就会对这个表进行几千次更新,更新速度很慢(每个exec 0.20次),而且他们使用的是唯一的列
IE:(注意,上面未显示COL A、B、C)更新测试集A =:1,B =:2,C =:3,其中X =:4,Y =:5,Z =:6

vvppvyoh

vvppvyoh1#

反向索引将每个列值的字节顺序反转。它们不会反转索引中列的顺序。因此,反向索引将存储:
BA 42 36
BA 42 56
DC 42 36
DC 42 56
FE 42 36
(in当然是甲骨文的编码格式,它不把数字存储为小数,所以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列)没有被颠倒。列相对于彼此的顺序没有改变。
反向索引的目的是将插入分散到叶节点上,这样在按顺序插入每个递增列值时就不会出现右前沿。如果遇到争用,这有助于减少争用。反转列顺序没有任何好处(如果愿意,您可以自己对列进行重新排序)。反向索引的缺点是,因为字节是以相反的顺序存储的,所以它们只能用于相等 predicate ,而不是像><BETWEENLIKE这样的不等式(它可以进行 * 全 * 扫描,但不能对起始值进行范围扫描/二进制搜索)。这使得它适用于没有顺序意义的标识符(如客户ID),但不包括日期、反映数量的数字、可能匹配模式的字符串,等。同样的好处可以通过哈希分区表上的一个唯一的列,并使索引本地。这也将分散插入到许多索引块,同时仍然保留做不等式搜索的能力。然而,这两种方法都不应该使用,除非热块争用实际上是一个问题。

u5i3ibmn

u5i3ibmn2#

除了Paul上面的回答之外,如果您正在使用反向键索引来缓解热块问题,则必须小心不要将热块内存问题更改为冷块物理IO问题。(我见过好几次),如果索引块不都在缓冲区缓存中。记住,通过使用反向键索引,你正在把索引分散到更多的块上。另一个可能的解决单调递增索引问题的方法是使用可伸缩序列

相关问题