CREATE TABLE foos ( batch_id NUMBER, creation_date DATE ) PARTITION BY RANGE (creation_date) SUBPARTITION BY HASH (batch_id) SUBPARTITION TEMPLATE ( SUBPARTITION H0, SUBPARTITION H1, SUBPARTITION H2, SUBPARTITION H3 ) ( PARTITION R0 VALUES LESS THAN (DATE'2018-04-01') ) ; CREATE INDEX foos_n1 ON foos (batch_id); INSERT INTO foos VALUES (1234, SYSDATE); INSERT INTO foos VALUES (1234, SYSDATE); INSERT INTO foos VALUES (1234, SYSDATE); INSERT INTO foos VALUES (1234, SYSDATE);
如果我知道batch_id,事先说1234
,那么确定它在此表中属于的子分区名称的最有效方法是什么,理想情况下,不必提交具有此值的行进入桌面?
我知道我可以这样做,但解释计划看起来很讨厌,并且要求批处理ID为{{1}}的行已经提交到表中
SELECT subpartition_name FROM ( SELECT ao.subobject_name subpartition_name FROM foos JOIN all_objects ao ON DBMS_ROWID.ROWID_OBJECT(foos.rowid) = ao.data_object_id WHERE 1=1 AND foos.batch_id = 1234 --AND ao.owner = 'ME' AND ao.object_name = 'FOOS' AND ao.object_type = 'TABLE SUBPARTITION' ) WHERE rownum = 1
答案 0 :(得分:2)
使用此测试数据
INSERT INTO foos VALUES (1234, SYSDATE);
INSERT INTO foos VALUES (1235, SYSDATE);
INSERT INTO foos VALUES (1236, SYSDATE);
如此处所述https://jonathanlewis.wordpress.com/2009/11/21/ora_hash-function/
ora_hash()函数的一个重要特性是它似乎是内部使用的函数 - 使用零种子 - 来确定行在散列分区表中属于哪个分区。当然,正如我在上一篇文章中指出的那样,你必须根据你声明的分区数量来定制函数的使用 - 为“最大桶”输入舍入到最接近的2的幂(并减去1) ,然后在结果中加一,然后如果分区数不是2的幂,则删除结果的最高位。
你得到了
with hsh as (
select BATCH_ID, ora_hash(BATCH_ID, 3)+1 subpartition_position from foos)
select BATCH_ID, SUBPARTITION_POSITION,
(select subpartition_name from user_tab_subpartitions where table_name = 'FOOS' and SUBPARTITION_POSITION = hsh.SUBPARTITION_POSITION) subpartition_name
from hsh;
BATCH_ID SUBPARTITION_POSITION SUBPARTITION_NAME
---------- --------------------- ------------------------------
1236 1 R0_H0
1235 3 R0_H2
1234 4 R0_H3
请注意,ora_hash
中的参数 3 是(子)分区的数量减1(= 4-1)。如果参考文献中描述的分区数不是2的幂(不是推荐值),则必须进行额外的处理。
您可以使用明确的分区查询验证结果,如下所示
select * from foos subpartition( R0_H0 ); -- 1236
select * from foos subpartition( R0_H1 ); -- empty
select * from foos subpartition( R0_H2 ); -- 1235
select * from foos subpartition( R0_H3 ); -- 1234
当然,它也适用于 1237 的新密钥,而不在表中。
with hsh as (
select 1237 BATCH_ID, ora_hash(1237, 3)+1 subpartition_position from dual)
select BATCH_ID, SUBPARTITION_POSITION,
(select subpartition_name from user_tab_subpartitions where table_name = 'FOOS' and SUBPARTITION_POSITION = hsh.SUBPARTITION_POSITION) subpartition_name
from hsh;
BATCH_ID SUBPARTITION_POSITION SUBPARTITION_NAME
---------- --------------------- ------------------------------
1237 2 R0_H1
“预测”子分区为R0_H1
,让* s查看INSERT的去向:
INSERT INTO foos VALUES (1237, SYSDATE);
select * from foos subpartition( R0_H1 ); -- 1237
但谨慎使用,因为它是IMO没有记录的功能......