How to tell which partition a row would go into, given a known partition key value in Oracle?

那年仲夏 提交于 2021-02-08 04:38:55

问题


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);

If I know a batch_id, say 1234 in advance, what is the most efficient way of determining the subpartition name that it would belong to in this table, ideally without having to have already committed a row with this value into the table?

I know I can do this, but the explain plan looks pretty nasty, and it requires that a row with a batch id of 1234 already be committed into the table

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:


With this test data

INSERT INTO foos VALUES (1234, SYSDATE);
INSERT INTO foos VALUES (1235, SYSDATE);
INSERT INTO foos VALUES (1236, SYSDATE);

As described here https://jonathanlewis.wordpress.com/2009/11/21/ora_hash-function/

One important feature of the ora_hash() function is that it seems to be the function used internally – with a zero seed – to determine which partition a row belongs to in a hash partitioned table. Of course, as I pointed out in the previous article, you have to tailor the use of the function to the number of partitions you have declared – rounding up to the nearest power of two (and subtracting one) for the “max bucket” input, then adding one to the result, then dropping the highest bit of the result if the number of partitions is not a power of two.

you get

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   

Note that the parameter 3 in ora_hash is the number of (sub)partitions subtracted by 1. (= 4-1). You'll have to do additional processing if the number of partition is not a power of two (which is not recommendet) as described in the reference.

You may verify the result with an explicite partition query as below

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

And of course it works also for new keys, new for 1237 which in not in the table.

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 

The "predicted" subpartition is R0_H1, let*s see where the INSERT will go:

INSERT INTO foos VALUES (1237, SYSDATE);      
select * from foos subpartition( R0_H1 ); --  1237

But use with caution, as it is IMO not documented feature ...



来源:https://stackoverflow.com/questions/49566194/how-to-tell-which-partition-a-row-would-go-into-given-a-known-partition-key-val

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!