考虑到Oracle中已知的分区键值,如何判断一行将进入哪个分区?

时间:2018-03-29 22:55:39

标签: oracle oracle12c

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

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没有记录的功能......