Partition pruning in the partition_wise join

Given tables table1 partitioned by hash on client_id column, and another table2 equipartitioned (hash on client_id column) I want to get both tables joined, but read the data partition by partition (in serial or from multiple client sessions). How to do this?
select * from table1 T1, table2 T2
where t1.client_id = t2.client_id
The query above works fine - it DOES partition_wise join, but i cant use it since huge amount of rows it returns. Id like to use
select *
from table1 partition (P1) T1 ,
table2 T2
where t1.client_id = t2.client_id
But in this case Oracle does not prune all Table2 partitions - it makes join between 1st partition of Table1 and all partitions of Table2. First question is why?
I can fix it by pointing table2 partition too, then second question is - how can I be sure that all corresponding partitions with the same order number (given uniform partitioning for several tables) contain same keys?

Using composite changes nothing. I've realized the problem - partition pruning is performed basing on "where" clause content. So, using "select from partition"
does not affect a joined table. Probably, creating "partition_id" column filled with
custom hash would solve the problem.

Similar Messages

  • Partition pruning not working for partitioned table joins

    Hi,
    We are joining  4 partitioned tables on partition column & other key columns. And we are filtering the driving table on partition key. But explain plan is showing that all tables except the driving table are not partition pruning and scanning all partitions.Is there any limitation that filter condition cannot be dynamic?
    Thanks a lot in advance.
    Here are the details...
    SELECT a.pay_prd_id,
                  a.a_id,
                  a.a_evnt_no
      FROM b,
                c,
                a,
                d
    WHERE  (    a.pay_prd_id = b.pay_prd_id ---partition range all
                AND a.a_evnt_no  = b.b_evnt_no
                AND a.a_id       = b.b_id
       AND (    a.pay_prd_id = c.pay_prd_id---partition range all
            AND a.a_evnt_no  = c.c_evnt_no
            AND a.a_id       = c.c_id
       AND (    a.pay_prd_id = d.pay_prd_id---partition range all
            AND a.a_evnt_no  = d.d_evnt_no
            AND a.a_id       = d.d_id
       AND (a.pay_prd_id =  ---partition range single
               CASE '201202'
                  WHEN 'YYYYMM'
                     THEN (SELECT min(pay_prd_id)
                                      FROM pay_prd
                                     WHERE pay_prd_stat_cd = 2)
                  ELSE TO_NUMBER ('201202', '999999')
               END
    DDLs.
    create table pay_prd
    pay_prd_id number(6),
    pay_prd_stat_cd integer,
    pay_prd_stat_desc varchar2(20),
    a_last_upd_dt DATE
    insert into pay_prd
    select 201202,2,'OPEN',sysdate from dual
    union all
    select 201201,1,'CLOSE',sysdate from dual
    union all
    select 201112,1,'CLOSE',sysdate from dual
    union all
    select 201111,1,'CLOSE',sysdate from dual
    union all
    select 201110,1,'CLOSE',sysdate from dual
    union all
    select 201109,1,'CLOSE',sysdate from dual
    CREATE TABLE A
    (PAY_PRD_ID    NUMBER(6) NOT NULL,
    A_ID        NUMBER(9) NOT NULL,
    A_EVNT_NO    NUMBER(3) NOT NULL,
    A_DAYS        NUMBER(3),
    A_LAST_UPD_DT    DATE
    PARTITION BY RANGE (PAY_PRD_ID)
    INTERVAL( 1)
      PARTITION A_0001 VALUES LESS THAN (201504)
    ENABLE ROW MOVEMENT;
    ALTER TABLE A ADD CONSTRAINT A_PK PRIMARY KEY (PAY_PRD_ID,A_ID,A_EVNT_NO) USING INDEX LOCAL;
    insert into a
    select 201202,1111,1,65,sysdate from dual
    union all
    select 201202,1111,2,75,sysdate from dual
    union all
    select 201202,1111,3,85,sysdate from dual
    union all
    select 201202,1111,4,95,sysdate from dual
    CREATE TABLE B
    (PAY_PRD_ID    NUMBER(6) NOT NULL,
    B_ID        NUMBER(9) NOT NULL,
    B_EVNT_NO    NUMBER(3) NOT NULL,
    B_DAYS        NUMBER(3),
    B_LAST_UPD_DT    DATE
    PARTITION BY RANGE (PAY_PRD_ID)
    INTERVAL( 1)
      PARTITION B_0001 VALUES LESS THAN (201504)
    ENABLE ROW MOVEMENT;
    ALTER TABLE B ADD CONSTRAINT B_PK PRIMARY KEY (PAY_PRD_ID,B_ID,B_EVNT_NO) USING INDEX LOCAL;
    insert into b
    select 201202,1111,1,15,sysdate from dual
    union all
    select 201202,1111,2,25,sysdate from dual
    union all
    select 201202,1111,3,35,sysdate from dual
    union all
    select 201202,1111,4,45,sysdate from dual
    CREATE TABLE C
    (PAY_PRD_ID    NUMBER(6) NOT NULL,
    C_ID        NUMBER(9) NOT NULL,
    C_EVNT_NO    NUMBER(3) NOT NULL,
    C_DAYS        NUMBER(3),
    C_LAST_UPD_DT    DATE
    PARTITION BY RANGE (PAY_PRD_ID)
    INTERVAL( 1)
      PARTITION C_0001 VALUES LESS THAN (201504)
    ENABLE ROW MOVEMENT;
    ALTER TABLE C ADD CONSTRAINT C_PK PRIMARY KEY (PAY_PRD_ID,C_ID,C_EVNT_NO) USING INDEX LOCAL;
    insert into c
    select 201202,1111,1,33,sysdate from dual
    union all
    select 201202,1111,2,44,sysdate from dual
    union all
    select 201202,1111,3,55,sysdate from dual
    union all
    select 201202,1111,4,66,sysdate from dual
    CREATE TABLE D
    (PAY_PRD_ID    NUMBER(6) NOT NULL,
    D_ID        NUMBER(9) NOT NULL,
    D_EVNT_NO    NUMBER(3) NOT NULL,
    D_DAYS        NUMBER(3),
    D_LAST_UPD_DT    DATE
    PARTITION BY RANGE (PAY_PRD_ID)
    INTERVAL( 1)
      PARTITION D_0001 VALUES LESS THAN (201504)
    ENABLE ROW MOVEMENT;
    ALTER TABLE D ADD CONSTRAINT D_PK PRIMARY KEY (PAY_PRD_ID,D_ID,D_EVNT_NO) USING INDEX LOCAL;
    insert into c
    select 201202,1111,1,33,sysdate from dual
    union all
    select 201202,1111,2,44,sysdate from dual
    union all
    select 201202,1111,3,55,sysdate from dual
    union all
    select 201202,1111,4,66,sysdate from dual

    Below query generated from Business Objects and submitted to Database (the case statement is generated by BO). Cant we use Case/Subquery/Decode etc for the partitioned column? We are assuming that  the case causing the issue to not to dynamic partition elimination on the other joined partitioned tables (TAB_B_RPT, TAB_C_RPT).
    SELECT TAB_D_RPT.acvy_amt,
           TAB_A_RPT.itnt_typ_desc,
           TAB_A_RPT.ls_typ_desc,
           TAB_A_RPT.evnt_no,
           TAB_C_RPT.pay_prd_id,
           TAB_B_RPT.id,
           TAB_A_RPT.to_mdfy,
           TAB_A_RPT.stat_desc
      FROM TAB_D_RPT,
           TAB_C_RPT fee_rpt,
           TAB_C_RPT,
           TAB_A_RPT,
           TAB_B_RPT
    WHERE (TAB_B_RPT.id = TAB_A_RPT.id)
       AND (    TAB_A_RPT.pay_prd_id = TAB_D_RPT.pay_prd_id -- expecting Partition Range Single, but doing Partition Range ALL
            AND TAB_A_RPT.evnt_no    = TAB_D_RPT.evnt_no
            AND TAB_A_RPT.id         = TAB_D_RPT.id
       AND (    TAB_A_RPT.pay_prd_id = TAB_C_RPT.pay_prd_id -- expecting Partition Range Single, but doing Partition Range ALL
            AND TAB_A_RPT.evnt_no    = TAB_C_RPT.evnt_no
            AND TAB_A_RPT.id         = TAB_C_RPT.id
       AND (    TAB_A_RPT.pay_prd_id = fee_rpt.pay_prd_id -- expecting Partition Range Single
            AND TAB_A_RPT.evnt_no    = fee_rpt.evnt_no
            AND TAB_A_RPT.id         = fee_rpt.id
       AND (TAB_A_RPT.rwnd_ind = 'N')
       AND (TAB_A_RPT.pay_prd_id =
               CASE '201202'
                  WHEN 'YYYYMM'
                     THEN (SELECT DISTINCT pay_prd.pay_prd_id
                                      FROM pay_prd
                                     WHERE pay_prd.stat_cd = 2)
                  ELSE TO_NUMBER ('201202', '999999')
               END
    And its explain plan is...
    Plan
    SELECT STATEMENT ALL_ROWS Cost: 79 K Bytes: 641 M Cardinality: 3 M
    18 HASH JOIN Cost: 79 K Bytes: 641 M Cardinality: 3 M
    3 PART JOIN FILTER CREATE SYS.:BF0000 Cost: 7 K Bytes: 72 M Cardinality: 3 M
    2 PARTITION RANGE ALL Cost: 7 K Bytes: 72 M Cardinality: 3 M Partition #: 3 Partitions accessed #1 - #1048575
    1 TABLE ACCESS FULL TABLE TAB_D_RPT Cost: 7 K Bytes: 72 M Cardinality: 3 M Partition #: 3 Partitions accessed #1 - #1048575
    17 HASH JOIN Cost: 57 K Bytes: 182 M Cardinality: 874 K
    14 PART JOIN FILTER CREATE SYS.:BF0001 Cost: 38 K Bytes: 87 M Cardinality: 914 K
    13 HASH JOIN Cost: 38 K Bytes: 87 M Cardinality: 914 K
    6 PART JOIN FILTER CREATE SYS.:BF0002 Cost: 8 K Bytes: 17 M Cardinality: 939 K
    5 PARTITION RANGE ALL Cost: 8 K Bytes: 17 M Cardinality: 939 K Partition #: 9 Partitions accessed #1 - #1048575
    4 TABLE ACCESS FULL TABLE TAB_C_RPT Cost: 8 K Bytes: 17 M Cardinality: 939 K Partition #: 9 Partitions accessed #1 - #1048575
    12 HASH JOIN Cost: 24 K Bytes: 74 M Cardinality: 957 K
    7 INDEX FAST FULL SCAN INDEX (UNIQUE) TAB_B_RPT_PK Cost: 675 Bytes: 10 M Cardinality: 941 K
    11 PARTITION RANGE SINGLE Cost: 18 K Bytes: 65 M Cardinality: 970 K Partition #: 13 Partitions accessed #KEY(AP)
    10 TABLE ACCESS FULL TABLE TAB_A_RPT Cost: 18 K Bytes: 65 M Cardinality: 970 K Partition #: 13 Partitions accessed #KEY(AP)
    9 HASH UNIQUE Cost: 4 Bytes: 14 Cardinality: 2
    8 TABLE ACCESS FULL TABLE PAY_PRD Cost: 3 Bytes: 14 Cardinality: 2
    16 PARTITION RANGE JOIN-FILTER Cost: 8 K Bytes: 106 M Cardinality: 939 K Partition #: 17 Partitions accessed #:BF0001
    15 TABLE ACCESS FULL TABLE TAB_C_RPT Cost: 8 K Bytes: 106 M Cardinality: 939 K Partition #: 17 Partitions accessed #:BF0001
    Thanks Again.

  • Partition Pruning - Dimension and FACT tables..

    Hi
    I have a DWH environment where we have partitioned the FACT table by a date column. This is RANGE partition. The TIME dimension table joins to the FACT table based on this date. However the end user queries will typically be fired using a different column in the time dimension that will hold more VIEWABLE date values (e.g.) in format MON-YYYY or YYYY-MM etc..
    The query is autogenerated by the viewer tool. The SQL has something like
    select sum(balance), MONTH from fact a, dim_time b
    where a.date = b.date and <-- this the partitioned key in fact
    b.month_year_col = 'Apr-2006' <-- Dimension filter.
    In the above case, Oracle is not doing PARTITION PRUNING. I have 24 period data and in the explain plan i can see it goes to the entire 24 periods. However if i change the query to
    select sum(balance), MONTH from fact a, dim_time b
    where a.date = b.date and <-- this the partitioned key in fact
    b.date = '31-Apr-2006' <-- Dimension filter.
    it does partition pruning. The explain plan shows that i goes to only one partition.
    Any help on this please. I would need the first query to use PARTITION PRUNING.
    Thanks
    bala

    Hi All
    Got it to work with these 3 parameters
    alter system set "_subquery_pruning_enabled" = true
    alter session set "_subquery_pruning_cost_factor"=1;
    alter session set "_subquery_pruning_reduction"=100;
    Thanks for all those who had a look into my question.
    Regards
    bala

  • Partition pruning

    Hi,
    We use Oracle 11.2.0.3 and are being aksed to considering implementing partitioning as follows:
    We will have a lrage fact table -several billion records
    structure is
    product_id,
    various other dimension _keys
    and the measures.
    It is a star schema and all the ids are surrogate keys which are fks to the dimension tables.
    Irt is being suggested to add extra column to the fact table - partitioning date and range-partition the sales fact and product dimenision by this new column and also the product dimension such that the join between the central sales atr becomes
    where sales.product_id = product.dimension_key
    and sales.partitiong_date = product.partioning_date
    On the basis that partition-pruning will occur.
    I'm no expert on partitioning but I'm not sure this will give th desired affect of partition-pruning as the partitioning-date column will not be referred to directly
    e. no queries wil say and partitiong_date = '27-OCT-2012'
    Will partition-pruning occure simply n fact fact table and dimesnion table now would have this extra join on them.
    Any advice would be great before we go down this path espeacilly if it is a dead-end in tersm of no material benefit or worse woudl make queries very slow.
    Thanks

    >
    Will partition-pruning occure simply n fact fact table and dimesnion table now would have this extra join on them.
    >
    No.
    >
    We use Oracle 11.2.0.3 and are being aksed to considering implementing partitioning
    >
    Why? You don't partition just because you can. You need a reason. Ask them why they want you to partition. What are you trying to achieve?
    >
    Do you have any suggestions how best to partition a fact table which only has surrogate keys and measures. No genuine date column as such like sales_date.
    >
    Not without knowing what goal you are trying to achieve. If you are trying to improve performance then you need to provide a sample query that you want to improve.
    If there is no partition pruning then performance will only be improved if the queries execute in PARALLEL.
    For partition pruning to occur there must be at least one filter predicate in the query that allows Oracle to determine which partitions the required data is in. .
    Partitioning on product_id will only allow pruning if the queries use product_id as a predicate. If it is a surrogate key and not a real value then users can't use it directly and so queries would likely only get the actual product_id value by using a lookup table from a product dimension table.
    So a lot more information is needed in order to provide any specific suggestions.
    1. What is the initial size of the table to be partitioned?
    2. How much DML activity (INSERTs, DELETEs, UPDATEs) is expected?
    3. Is the DML in #2 daily, weekly, monthly?
    4. Is there a need to remove old data periodically? For example keep three years online and each month remove the oldest month?
    5. What are the typical columns being filtered on when users query the data?
    6. Is the an OLTP system or datawarehouse?

  • Partition Pruning vs Partition-Wise Join

    Hi,
    I am not sure if this is the right place for this question, but here it goes.
    I am in a situation where in the begining I have to join two big tables without any where clauses. It is pretty much a Caretsian Product where a criteria meets (Internal Code), but I have to join all rows. (Seems like a good place for Partition-Wise Join).
    Later I only need to update certain rows based on a key value (Customer ID, Region ID). (Good candidate for Partition Pruning).
    What would be the best option. Is there a way to use both?
    Assume that following:
    Table 1 has the structure of
    Customer ID
    Internal Code
    Other Data
    There are about 1000 Customer ID. Each Customer ID has 1000 Internal Codes.
    Table 2 has the structure of
    Region ID
    Internal Code
    Other Data
    There are about 5000 Region ID. Each Region ID has 1000 Internal Codes(same as Table 1).
    I am currently thinking of doing a HASH PARTITION (8 partitions) on Customer ID for Table 1 and HASH PARTITION (8 partitions) on Region ID for Table 2.
    The initial insert will take a long time, but when I go to update the joined data based on specific Customer ID, or Region ID atleast from one Table only one Partition will be used.
    I would sincerely appreciate some advice from the gurus.
    Thanks...

    Hi,
    I still don't understand what it is that you are trying to do.
    Would it be possible for you to create a silly example with just a few rows
    to show us what it is that you are trying to accomplish?
    Then we can help you solve whatever problem it is that you are having.
    create table t1(
       customer_id   number       not null
      ,internal_code varchar2(20) not null
      ,<other_columns>
      ,constraint t1_pk primary key(customer_id, internal_code)
    create table t2(
       region_id number not null
      ,internal_code varchar2(20) not null
      ,<other_columns>
      ,constraint t2_pk primary key(region_id, internal_code)
    insert into t1(customer_id, internal_code, ...) values(...);
    insert into t1(customer_id, internal_code, ...) values(...);
    insert into t2(region_id, internal_code, ...) values(...);
    insert into t2(region_id, internal_code, ...) values(...);
    select <the rating calculation>
       from t1 join t2 using(internal_code);

  • Reference partitioning and partition pruning

    Hi All,
    I am on v 11.2.0.3.
    I have a pair of typical parent-child tables. Child table is growing like hell, hence we want to partition it, which will be used for deleting/dropping old data later on.
    There is no partitioning key in the child table which I can use for relating the data to the time when data was created. So, I thought I can use the timestamp from parent table for partitioning the parent table and reference partition the child table.
    I am more concerned about the child table (or the queries running on the child table) in terms of performance. ITEM_LIST_ID from the child table is extensively used in queries to access data from child table.
    How will partition pruning work when the child table is queried on the foreign key? will it every time go to the parent table, find out the partition and then resolve the partition for child table?
    The setup is given in the scripts below, will it cause lot of locking (to resolve partitions)? or am I worrying for nothing?
    Here are the scripts
    CREATE TABLE ITEM_LISTS /* Parent table, tens of thousands of records */
      ITEM_LIST_ID    NUMBER(10)     NOT NULL PRIMARY KEY, /* Global index on partitioned table !!! */
      LIST_NAME       VARCHAR2(500)  NOT NULL,
      FIRST_INSERTED  TIMESTAMP(6)   NOT NULL
    PARTITION BY RANGE ( FIRST_INSERTED )
      partition p0 values less than ( to_date('20130101','YYYYMMDD') ),
      partition p201301 values less than ( to_date('20130201','YYYYMMDD') ),
      partition p201302 values less than ( to_date('20130301','YYYYMMDD') ),
      partition p201303 values less than ( to_date('20130401','YYYYMMDD') ),
      partition p201304 values less than ( to_date('20130501','YYYYMMDD') ),
      partition p201305 values less than ( to_date('20130601','YYYYMMDD') )
    CREATE INDEX ITEM_LISTS_IDX1 ON ITEM_LISTS ( LIST_NAME ) LOCAL ;
    CREATE TABLE ITEM_LIST_DETAILS /* Child table, millions of records */
      ITEM_ID        NUMBER(10)     NOT NULL,
      ITEM_LIST_ID   NUMBER(10)     NOT NULL, /* Always used in WHERE clause by lots of big queries */
      CODE           VARCHAR2(30)   NOT NULL,
      ALT_CODE       VARCHAR2(30)   NOT NULL,
      CONSTRAINT   ITEM_LIST_DETAILS_FK
      FOREIGN KEY  ( ITEM_LIST_ID ) REFERENCES ITEM_LISTS
    PARTITION BY REFERENCE ( ITEM_LIST_DETAILS_FK )
    CREATE INDEX ITEM_LIST_DETAILS_IDX1 ON ITEM_LIST_DETAILS (ITEM_ID) LOCAL;
    CREATE INDEX ITEM_LIST_DETAILS_IDX2 ON ITEM_LIST_DETAILS (ITEM_LIST_ID, CODE) LOCAL;Any thoughts / opinions / corrections ?
    Thanks in advance

    To check how partition pruning works here, I inserted some data in these tables. Inserted data in ITEM_LISTS (parent) from DBA_OBJECTS ( object_id => item_list_id, object_name => list_name, first_inserted => manually created). Also created corresponding child data in ITEM_LIST_DETAILS, so that, for every item_list_id in parent about 5000 records go in child table.
    Looking at the queries and plan below, my question is, what exactly does the operations "PARTITION REFERENCE SINGLE" and "PARTITION REFERENCE ITERATOR" imply ??
    I gave a search on "PARTITION REFERENCE ITERATOR" in Oracle 11.2 documentation, it says "No exact match found" !!
    /* Direct query on child table */
    SQL> select count(*) from item_list_details where item_list_id = 6323 ;
      COUNT(*)
          5000
    1 row selected.
    Execution Plan
    Plan hash value: 2798904155
    | Id  | Operation                   | Name                   | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT            |                        |     1 |     5 |    22   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE             |                        |     1 |     5 |            |          |       |       |
    |   2 |   PARTITION REFERENCE SINGLE|                        |  5000 | 25000 |    22   (0)| 00:00:01 |   KEY |   KEY |
    |*  3 |    INDEX RANGE SCAN         | ITEM_LIST_DETAILS_IDX2 |  5000 | 25000 |    22   (0)| 00:00:01 |   KEY |   KEY |
    Predicate Information (identified by operation id):
       3 - access("ITEM_LIST_ID"=6323)
    SQL> select * from temp1; /* Dummy table to try out some joins */
    OBJECT_ID OBJECT_NAME
          6598 WRH$_INTERCONNECT_PINGS
    1 row selected.
    /* Query on child table, joining with some other table */
    SQL> select count(*)
      2  from temp1 d, ITEM_LIST_DETAILS i1
      3  where d.object_id = i1.item_list_id
      4  and d.object_name = 'WRH$_INTERCONNECT_PINGS';
      COUNT(*)
          5000
    1 row selected.
    Execution Plan
    Plan hash value: 2288153583
    | Id  | Operation                      | Name                   | Rows  | Bytes | Cost (%CPU)| Time  | Pstart| Pstop |
    |   0 | SELECT STATEMENT               |                        |     1 |    70 |    24   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE                |                        |     1 |    70 |            |       |  |       |
    |   2 |   NESTED LOOPS                 |                        |  5000 |   341K|    24   (0)| 00:00:01 |       |       |
    |*  3 |    TABLE ACCESS FULL           | TEMP1                  |     1 |    65 |     3   (0)| 00:00:01 |       |       |
    |   4 |    PARTITION REFERENCE ITERATOR|                        |  5000 | 25000 |    21   (0)| 00:00:01 |   KEY |   KEY |
    |*  5 |     INDEX RANGE SCAN           | ITEM_LIST_DETAILS_IDX2 |  5000 | 25000 |    21   (0)| 00:00:01 |   KEY |   KEY |
    Predicate Information (identified by operation id):
       3 - filter("D"."OBJECT_NAME"='WRH$_INTERCONNECT_PINGS')
       5 - access("D"."OBJECT_ID"="I1"."ITEM_LIST_ID")

  • Star transformation and Partition pruning

    All experts,
    I need advice on my situation -
    I have data warehouse running on oracle 11.2.0.1
    We are using star trnasformation. The fact table is partitioned.
    However, with the star query (fact joined to dimensions with keys and filters only on dimensions), partition pruning is not happening.
    I read some documents online and it seems that partition pruning is not going to happen unless I directly filter fact (which is against the best paractices of star query).
    Please advice

    SELECT
    PTL_EDW.D_TIME.CAL_YYYYMM,
    (( ( ( sum(PTL_EDWPERF.F_JOB_OIL_COST.LABOR_COST) )+( sum(PTL_EDWPERF.F_JOB_OIL_COST.OUTSIDE_COST) )+( sum(PTL_EDWPERF.F_JOB_OIL_COST.PARTS_COST) ) )-( ( sum(PTL_EDWPERF.F_JOB_OIL_COST.RECOVERY_LABOR_AMOUNT) )+( sum(PTL_EDWPERF.F_JOB_OIL_COST.RECOVERY_OUTSIDE_AMOUNT) )+( sum(PTL_EDWPERF.F_JOB_OIL_COST.RECOVERY_PARTS_AMOUNT) ) )+( ( sum(PTL_EDWPERF.F_JOB_OIL_COST.WARRANTY_LABOR_AMOUNT) )+( sum(PTL_EDWPERF.F_JOB_OIL_COST.WARRANTY_OUTSIDE_AMOUNT) )+( sum(PTL_EDWPERF.F_JOB_OIL_COST.WARRANTY_PARTS_AMOUNT) ) ) )+( sum(PTL_EDWPERF.F_JOB_OIL_COST.OIL_COST) ))
    FROM
    PTL_EDWPERF.F_JOB_OIL_COST,
    PTL_EDW.D_LOCATION_MASTER D_LOCATION_DOMICILE,
    PTL_EDW.D_VEHICLE_CAP_STATUS,
    PTL_EDW.D_UNIT_MASTER,
    PTL_EDW.D_ACCOUNT_CODE,
    PTL_EDW.D_TIME
    WHERE
    ( PTL_EDWPERF.F_JOB_OIL_COST.ACCOUNT_CODE_KEY = PTL_EDW.D_ACCOUNT_CODE.ACCOUNT_CODE_KEY)
    AND ( PTL_EDWPERF.F_JOB_OIL_COST.VEHICLE_CAP_STATUS_KEY=PTL_EDW.D_VEHICLE_CAP_STATUS.VEHICLE_CAP_STATUS_KEY )
    AND ( PTL_EDWPERF.F_JOB_OIL_COST.CHARGING_LOCATION_KEY=D_LOCATION_DOMICILE.LOCATION_MASTER_KEY )
    AND (PTL_EDWPERF.F_JOB_OIL_COST.UNIT_MASTER_KEY = PTL_EDW.D_UNIT_MASTER.UNIT_MASTER_KEY)
    AND (PTL_EDWPERF.F_JOB_OIL_COST.RO_ACCOUNTING_MONTH_KEY = PTL_EDW.D_TIME.TIME_KEY)
    AND ( exists (select 1 from ptl_edw.s_location where s_location.ssoid = '600028988' and PTL_EDWPERF.F_JOB_OIL_COST.CHARGING_LOCATION_KEY = decode(s_location.location_master_key, -99999, PTL_EDWPERF.F_JOB_OIL_COST.CHARGING_LOCATION_KEY, s_location.location_master_key)) )
    AND
    --PTL_EDWPERF.F_JOB_OIL_COST.PARTITION_KEY  BETWEEN  201011  AND  201104
    PTL_EDW.D_TIME.CAL_YYYYMM BETWEEN 200601 AND 201104
    AND
    D_LOCATION_DOMICILE.CORP_CD IN ( '2000','HPTL' )
    AND
    ( ( PTL_EDW.D_VEHICLE_CAP_STATUS.VEHICLE_CAP_STATUS ) IN ( 'ACCRUED','ACTIVE' ) )
    AND
    ( PTL_EDW.D_UNIT_MASTER.CONTRACT_GROUP = 'P' )
    AND
    PTL_EDW.D_UNIT_MASTER.UNIT_CATEGORY IN ( 'TRACTOR','TRAILER','TRUCK' )
    AND
    PTL_EDW.D_ACCOUNT_CODE.ACCOUNT_CODE_GROUP1 IN ( 'COMMERCIAL RENTAL','CONTRACT MAINTENANCE - GUAR','CONTRACT MAINTENANCE - OTHER','CONTRACT MAINTENANCE - PEG','LEASE','TRAILER PLUS' )
    GROUP BY
    PTL_EDW.D_TIME.CAL_YYYYMM
    -- bg4643wj2d3xn
    =====================================
    Elapsed: 00:39:35.08
    Execution Plan
    Plan hash value: 2317670688
    | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
    | 0 | SELECT STATEMENT | | 9 | 666 | | 186K (1)| 00:43:36 | | |
    | 1 | HASH GROUP BY | | 9 | 666 | | 186K (1)| 00:43:36 | | |
    |* 2 | FILTER | | | | | | | | |
    |* 3 | HASH JOIN | | 557K| 39M| | 186K (1)| 00:43:35 | | |
    |* 4 | VIEW | index$_join$_006 | 1925 | 19250 | | 16 (7)| 00:00:01 | | |
    |* 5 | HASH JOIN | | | | | | | | |
    |* 6 | INDEX RANGE SCAN | D_TIME_CALYYYYMM_IDX2 | 1925 | 19250 | | 5 (20)| 00:00:01 | | |
    | 7 | INDEX FAST FULL SCAN | D_TIME_TIME_KEY_PK | 1925 | 19250 | | 14 (0)| 00:00:01 | | |
    |* 8 | HASH JOIN | | 557K| 34M| 32M| 186K (1)| 00:43:34 | | |
    | 9 | PARTITION RANGE ALL | | 557K| 26M| | 131K (1)| 00:30:46 | 1 | 133 |
    | 10 | TABLE ACCESS BY LOCAL INDEX ROWID| F_JOB_OIL_COST | 557K| 26M| | 131K (1)| 00:30:46 | 1 | 133 |
    | 11 | BITMAP CONVERSION TO ROWIDS | | | | | | | | |
    | 12 | BITMAP AND | | | | | | | | |
    | 13 | BITMAP MERGE | | | | | | | | |
    | 14 | BITMAP KEY ITERATION | | | | | | | | |
    | 15 | BUFFER SORT | | | | | | | | |
    |* 16 | VIEW | index$_join$_179 | 2 | 20 | | 2 (50)| 00:00:01 | | |
    |* 17 | HASH JOIN | | | | | | | | |
    | 18 | INLIST ITERATOR | | | | | | | | |
    |* 19 | INDEX UNIQUE SCAN | D_CAPSTS_ETL_IDX | 2 | 20 | | 0 (0)| 00:00:01 | | |
    | 20 | INDEX FAST FULL SCAN | D_VEHICLE_CAP_STATUS_PK | 2 | 20 | | 1 (0)| 00:00:01 | | |
    |* 21 | BITMAP INDEX RANGE SCAN | BIMAP_JOBOIL_COST_VEH_CAP_KY | | | | | | 1 | 133 |
    | 22 | BITMAP MERGE | | | | | | | | |
    | 23 | BITMAP KEY ITERATION | | | | | | | | |
    | 24 | BUFFER SORT | | | | | | | | |
    |* 25 | TABLE ACCESS FULL | D_TIME | 1925 | 51975 | | 19 (6)| 00:00:01 | | |
    |* 26 | BITMAP INDEX RANGE SCAN | BIMAP_JOBOIL_CST_RO_ACC_MTH_KY | | | | | | 1 | 133 |
    | 27 | BITMAP MERGE | | | | | | | | |
    | 28 | BITMAP KEY ITERATION | | | | | | | | |
    | 29 | BUFFER SORT | | | | | | | | |
    |* 30 | TABLE ACCESS FULL | D_ACCOUNT_CODE | 11 | 165 | | 4 (0)| 00:00:01 | | |
    |* 31 | BITMAP INDEX RANGE SCAN | BIMAP_JOBOIL_COST_ACCT_CODE_KY | | | | | | 1 | 133 |
    | 32 | BITMAP MERGE | | | | | | | | |
    | 33 | BITMAP KEY ITERATION | | | | | | | | |
    | 34 | BUFFER SORT | | | | | | | | |
    |* 35 | VIEW | index$_join$_172 | 3136 | 28224 | | 19 (6)| 00:00:01 | | |
    |* 36 | HASH JOIN | | | | | | | | |
    | 37 | INLIST ITERATOR | | | | | | | | |
    |* 38 | INDEX RANGE SCAN | D_LOCNMST_ETL_IDX | 3136 | 28224 | | 12 (17)| 00:00:01 | | |
    | 39 | INDEX FAST FULL SCAN | LOCATION_MASTER_KEY_PK | 3136 | 28224 | | 10 (0)| 00:00:01 | | |
    |* 40 | BITMAP INDEX RANGE SCAN | BIMAP_JOBOIL_COST_CHRG_LOCN_KY | | | | | | 1 | 133 |
    |* 41 | TABLE ACCESS FULL | D_UNIT_MASTER | 1790K| 23M| | 51484 (2)| 00:12:01 | | |
    |* 42 | TABLE ACCESS BY INDEX ROWID | S_LOCATION | 1 | 23 | | 12 (0)| 00:00:01 | | |
    |* 43 | INDEX RANGE SCAN | S_LOCN_SSOID_IDX | 14 | | | 1 (0)| 00:00:01 | | |
    Predicate Information (identified by operation id):
    2 - filter( EXISTS (SELECT 0 FROM "PTL_EDW"."S_LOCATION" "S_LOCATION" WHERE "S_LOCATION"."SSOID"='600028988' AND
    DECODE("S_LOCATION"."LOCATION_MASTER_KEY",(-99999),:B1,"S_LOCATION"."LOCATION_MASTER_KEY")=:B2))
    3 - access("F_JOB_OIL_COST"."RO_ACCOUNTING_MONTH_KEY"="D_TIME"."TIME_KEY")
    4 - filter("D_TIME"."CAL_YYYYMM">=200601 AND "D_TIME"."CAL_YYYYMM"<=201104)
    5 - access(ROWID=ROWID)
    6 - access("D_TIME"."CAL_YYYYMM">=200601 AND "D_TIME"."CAL_YYYYMM"<=201104)
    8 - access("F_JOB_OIL_COST"."UNIT_MASTER_KEY"="D_UNIT_MASTER"."UNIT_MASTER_KEY")
    16 - filter("D_VEHICLE_CAP_STATUS"."VEHICLE_CAP_STATUS"='ACCRUED' OR "D_VEHICLE_CAP_STATUS"."VEHICLE_CAP_STATUS"='ACTIVE')
    17 - access(ROWID=ROWID)
    19 - access("D_VEHICLE_CAP_STATUS"."VEHICLE_CAP_STATUS"='ACCRUED' OR "D_VEHICLE_CAP_STATUS"."VEHICLE_CAP_STATUS"='ACTIVE')
    21 - access("F_JOB_OIL_COST"."VEHICLE_CAP_STATUS_KEY"="D_VEHICLE_CAP_STATUS"."VEHICLE_CAP_STATUS_KEY")
    25 - filter("D_TIME"."CAL_YYYYMM">=200601 AND "D_TIME"."CAL_YYYYMM"<=201104)
    26 - access("F_JOB_OIL_COST"."RO_ACCOUNTING_MONTH_KEY"="D_TIME"."TIME_KEY")
    30 - filter("D_ACCOUNT_CODE"."ACCOUNT_CODE_GROUP1"='COMMERCIAL RENTAL' OR "D_ACCOUNT_CODE"."ACCOUNT_CODE_GROUP1"='CONTRACT MAINTENANCE
    - GUAR' OR "D_ACCOUNT_CODE"."ACCOUNT_CODE_GROUP1"='CONTRACT MAINTENANCE - OTHER' OR "D_ACCOUNT_CODE"."ACCOUNT_CODE_GROUP1"='CONTRACT
    MAINTENANCE - PEG' OR "D_ACCOUNT_CODE"."ACCOUNT_CODE_GROUP1"='LEASE' OR "D_ACCOUNT_CODE"."ACCOUNT_CODE_GROUP1"='TRAILER PLUS')
    31 - access("F_JOB_OIL_COST"."ACCOUNT_CODE_KEY"="D_ACCOUNT_CODE"."ACCOUNT_CODE_KEY")
    35 - filter("D_LOCATION_DOMICILE"."CORP_CD"='2000' OR "D_LOCATION_DOMICILE"."CORP_CD"='HPTL')
    36 - access(ROWID=ROWID)
    38 - access("D_LOCATION_DOMICILE"."CORP_CD"='2000' OR "D_LOCATION_DOMICILE"."CORP_CD"='HPTL')
    40 - access("F_JOB_OIL_COST"."CHARGING_LOCATION_KEY"="D_LOCATION_DOMICILE"."LOCATION_MASTER_KEY")
    41 - filter("D_UNIT_MASTER"."CONTRACT_GROUP"='P' AND ("D_UNIT_MASTER"."UNIT_CATEGORY"='TRACTOR' OR
    "D_UNIT_MASTER"."UNIT_CATEGORY"='TRAILER' OR "D_UNIT_MASTER"."UNIT_CATEGORY"='TRUCK'))
    42 - filter(DECODE("S_LOCATION"."LOCATION_MASTER_KEY",(-99999),:B1,"S_LOCATION"."LOCATION_MASTER_KEY")=:B2)
    43 - access("S_LOCATION"."SSOID"='600028988')
    Note
    - star transformation used for this statement
    Statistics
    3034 recursive calls
    0 db block gets
    28519518 consistent gets
    1075291 physical reads
    0 redo size
    2519 bytes sent via SQL*Net to client
    567 bytes received via SQL*Net from client
    6 SQL*Net roundtrips to/from client
    4 sorts (memory)
    0 sorts (disk)
    64 rows processed
    Partition is range on YYYYMM(numeric format)

  • Partition Pruning Aint Happening

    I have a situation where Oracle pruning is not happening and this situation is getting worse when the search criteria is close to current date.
    Table has a date based partition. SQL Statement has 2 partitioned tables. Date range is applied on a relatively smaller daily partitioned table and further joined to the next table (Its also date based partition). First table has partition column in the where clause and it joins to the next table using the partitioned column.
    SQL does partition pruning even for a month range search if the date range is in August. It will do partition pruning only for 25 days for september where clause. Likewise the where clause date range ability for partition pruning goes down and It will only do partition pruning for where clause with 5 days. If the where clause has more than 6 days (Mar 01 Thru Mar 06) in March 2009, Oracle does All partitions.
    Query is examined and it contains partition column in the where clause and we have also gathered 100% statistics of the table which is not partition pruning. Data growth is happening relatively each month.
    Sample: -
    Select 1
    From TAB1, TAB2
    Where TAB1.SELECT_DATE >= '01JAN2009
    And TAB1.SELECT_DATE <= '31JAN2009
    And TAB2.DATE_SELECT = TAB1.DATE_SELECT
    TAB1 Is a daily partition with SELECT_DATE column. Oracle is able to successfully do partition pruning on this table. But TAB2 partition pruning is not happening.
    How I can overcome this situation? Thanks for your help.
    Here is the explain plan for the SQL statement

    | Id  | Operation                            | Name         | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT                     |              |  1224 | 96696 |       |   978K  (4)| 01:21:35 |       |       |
    |   1 |  HASH GROUP BY                       |              |  1224 | 96696 |       |   978K  (4)| 01:21:35 |       |       |
    |*  2 |   HASH JOIN                          |              |  1122K|    84M|    49M|   978K  (4)| 01:21:34 |       |       |
    |*  3 |    HASH JOIN                         |              |  1122K|    36M|       |  5218   (4)| 00:00:27 |       |       |
    |   4 |     COLLECTION ITERATOR PICKLER FETCH| TABLE FUNC   |       |       |       |            |          |       |       |
    |   5 |     PARTITION RANGE ITERATOR         |              |   729K|    22M|       |  5145   (3)| 00:00:26 |   413 |   422 |
    |   6 |      PARTITION LIST ALL              |              |   729K|    22M|       |  5145   (3)| 00:00:26 |     1 |     2 |
    |*  7 |       MAT_VIEW ACCESS FULL           | TAB_01       |   729K|    22M|       |  5145   (3)| 00:00:26 |   825 |   844 |
    |   8 |    PARTITION RANGE ALL               |              |    84M|  3623M|       |   575K  (5)| 00:47:59 |     1 |   970 |
    |   9 |     TABLE ACCESS FULL                | TAB_02       |    84M|  3623M|       |   575K  (5)| 00:47:59 |     1 |   970 |
    Predicate Information (identified by operation id):
       2 - access("TAB_02"."SELECT_DATE"="TAB_01"."SELECT_DATE" AND "TAB_02"."SELECT_NUMBER"="TAB_01"."SELECT_NUMBER")
       3 - access("TAB_01"."TAG_ID"=SYS_OP_ATG(VALUE(KOKBF$),16,17,2))
       7 - filter("TAB_01"."SELECT_DATE"<=TO_DATE('2009-02-10 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))Following is the explain paln where partition elimination happening for a shorter date range search
    | Id  | Operation                            | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT                     |              |   714 | 56406 |   851K  (1)| 01:10:56 |       |       |
    |   1 |  HASH GROUP BY                       |              |   714 | 56406 |   851K  (1)| 01:10:56 |       |       |
    |   2 |   NESTED LOOPS                       |              |   621K|    46M|   850K  (1)| 01:10:55 |       |       |
    |*  3 |    HASH JOIN                         |              |   621K|    20M|  3210   (3)| 00:00:17 |       |       |
    |   4 |     COLLECTION ITERATOR PICKLER FETCH| TABLE FUNC   |       |       |            |          |       |       |
    |   5 |     PARTITION RANGE ITERATOR         |              |   403K|    12M|  3152   (3)| 00:00:16 |   413 |   418 |
    |   6 |      PARTITION LIST ALL              |              |   403K|    12M|  3152   (3)| 00:00:16 |     1 |     2 |
    |*  7 |       MAT_VIEW ACCESS FULL           | TAB_01       |   403K|    12M|  3152   (3)| 00:00:16 |   825 |   836 |
    |   8 |    PARTITION RANGE ITERATOR          |              |     1 |    45 |     2   (0)| 00:00:01 |   KEY |   KEY |
    |   9 |     TABLE ACCESS BY LOCAL INDEX ROWID| TAB_02       |     1 |    45 |     2   (0)| 00:00:01 |   KEY |   KEY |
    |* 10 |      INDEX RANGE SCAN                | TAB_02_PK    |     1 |       |     1   (0)| 00:00:01 |   KEY |   KEY |
    Predicate Information (identified by operation id):
       3 - access("TAB_01"."TAG_ID"=SYS_OP_ATG(VALUE(KOKBF$),16,17,2))
       7 - filter("TAB_01"."SELECT_DATE"<=TO_DATE('2009-02-06 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
      10 - access("TAB_02"."SELECT_DATE"="TAB_01"."SELECT_DATE" AND "TAB_02"."SELECT_NUMBER"="TAB_01"."SELECT_NUMBER")Query where partition elimination not happening on the second table is having date range of 7 days or more. SO the first explain plan is for Feb-01 Thru Feb 10 search
    Query where partition elimination happening on the second table is having date range of 7 days or less. The second explain plan is for Feb-01 Thru Feb-06 search
    This is great.
    Edited by: user10929035 on Mar 24, 2009 8:18 AM                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

  • Partition Pruning not working with "Transformation"

    Hello,
    we have a 10gR2 RAC at our customer and because every Report is reporting on Monthly-Basis, we partitioned the Fact-Tables by Month.
    That's working fine for our "normal" queries, where the Dimension-Table is joined to the Fact-Table and the Filter is on one Dimension-Column.
    Example:
    select     Dim.LT3_KEY,
         sum(Fact.VPR_GC_PER_FULL1) metric
    from     MART.V_PDM_RU_AGG_PROK_03     Fact
         join     MART.L_PERIODS     Dim
         on      (Fact.LT3_KEY = Dim.LT3_KEY)
    where Dim.LT3_SEQ_MARK = -2
    group by Dim.LT3_KEY
    The Fact-Table is "pruned" and only the one partition selected by "Dim.LT3_SEQ_MARK = -2" is read.
    This leads to 1.9 seconds runtime.
    Now the Problem:
    We have special Transformation-Metrics. This leads to a second join of the same Dimension to the Fact-Table.
    Problem: The Filter/Where-Clause is on the Second Dimesnion-Table and with this, Oracle will no longer prune.
    Example:
    select     Dim2.LT3_KEY,
         sum(Fact.VPR_GC_PER_FULL1) metric
    from     MART.V_PDM_RU_AGG_PROK_03     Fact
         join     MART.L_PERIODS     Dim1
         on      (Fact.LT3_KEY = Dim1.LT3_KEY)
         join     MART.L_PERIODS     Dim2
         on      (Dim1.LT3_KEY = Dim2.LT3_SM_LYEAR_1)
    where Dim2.LT3_SEQ_MARK = -2
    group by Dim2.LT3_KEY
    This SQL needs 26 Seconds, because it reads all data, not only the relevant.
    Of course, I can re-write that query but this is not possible in our environ,ment.
    Question: Is there any trick, hint, index to build, configuration or something else I can do to get the Oracle to prune also with the second query. The query should remain exactly the same as it is now?
    Thanks in advance.
    Frank
    P.S.: I now, that following query delivers the same and is working with pruning. But I can not change the build-process of the query.
    select     Dim.LT3_KEY,
         sum(Fact.VPR_GC_PER_FULL1) metric
    from     MART.V_PDM_RU_AGG_PROK_03     Fact
         join     MART.L_PERIODS     Dim
         on      (Fact.LT3_KEY = Dim.LT3_SM_LYEAR_1)
    where Dim.LT3_SEQ_MARK = -2
    group by Dim.LT3_KEY

    Hi Frank,
    it seems that the second join "on (Dim1.LT3_KEY = Dim2.LT3_SM_LYEAR_1)" on the same table (L_PERIODS as dim1 and dim2) forced the oracle optimizer to read the whole table instead of using indexes.
    There are several ways to tune this statement. Here are a few things i would try:
    If both columns (LT3_KEY) and (LT3_SM_LYEAR_1) are indexed with a single index you may force the optimizer with an oracle hint:
    /*+ INDEX (DIM2 <indexname for LT3_SM_LYEAR_1>) INDEX (DIM1 <indexname for LT3_KEY)> */
    to use them.
    You may switch both "index-Hints" to see, if there are different results in runtime.
    Another hint could help the optimizer first to join DIM1 with DIM2 and join the against the fact table:
    /*+ LEADING(dim2 dim1 fact) */
    You may test the statement with a new combined index (LT3_KEY, LT3_SM_LYEAR_1) or in reverse order ( LT3_SM_LYEAR_1, LT3_KEY). after this you may experience with the given optimizer hints and rerun the query.
    Maybe its a good idea to make indexes more "useful" to the optimizer as "full table scans". This worked good with oracle version prior 10, so maybe you want to try this hint to force oracle to use indexes in your query:
    /*+ OPT_PARAM('optimizer_index_cost_adj' 'xx') */
    where xx is a value lower than 100, try with 40 to see if there are changes to the execution plan.
    Don't forget to use the ALIAS object-names instead of physical names in optimizer hints, because otherwise they never work ...
    And sometimes FULL SCANS are not that bad ...

  • 11g new feature "Partition pruning based on bloom filtering" is what?

    While idly reading the Oracle 11g Database New Features I stumbled upon the following - BEGIN QUOTE:
    1.11.1.2 Enhanced Partition Pruning Capabilities
    Partition pruning now uses bloom filtering instead of subquery pruning. While subquery pruning was activated on a cost-based decision and consumed internal (recursive) resources, pruning based on bloom filtering is activated all the time without consuming additional resources.
    END QUOTE
    I haven't found any other references to bloom filtering in the manuals, and very few via google and MetaLink. So I am left wondering what the above paragraph actually means?
    Best regards,
    Hans Henrik Krohn

    Hi Hans
    The problem of subquery pruning is that part of the SQL statement is executed twice. Therefore, a cost-based decision is necessary to decide if it makes to do it or not...
    To avoid this double execution they introduced join-filter pruning (which takes advantage of a bloom filter). Since this new method has a very small overhead, it makes always sense to use it if pruning can be used. With it you will see execution plans like the following one.
    | Operation                           | Name    | Pstart| Pstop |
    | HASH JOIN                           |         |       |       |
    |  PART JOIN FILTER CREATE            | :BF0000 |       |       |
    |   TABLE ACCESS BY GLOBAL INDEX ROWID| T       | ROWID | ROWID |
    |    INDEX UNIQUE SCAN                | T_PK    |       |       |
    |  PARTITION RANGE JOIN-FILTER        |         |:BF0000|:BF0000|
    |   TABLE ACCESS FULL                 | T       |:BF0000|:BF0000|
    -----------------------------------------------------------------HTH
    Chris

  • Partitioning Pruning

    Hii Folks,
    I have two tables(test1 and test2) having partitions . There r no indexes on these tables. now i create a view on these tables like
    create or replace view my_vw
    as
    select  name , age , date_load from test1
    union all
    select name , age , date_load from test2
    now when i select from this view(my_vw) ,
    select from my_vw*
    *where date > date1*
    *and date <= date2*
    now this query dose a full table scan.
    i want the query to scan only the particular partiton and not the full table...
    I have a constraint that I cannot use indexes!!!!!
    what can i do in this case??
    Thnx in advance.

    Commander wrote:
    hey its range partition and the tables are huge and test1 and test2 are not identical. I will be doing some joins while creating the view. Now when i select from the view and see the explain plan than I c a full table scan.Can you show us the output of EXPLAIN PLAN using DBMS_XPLAN.DISPLAY when querying your view using the predicates? Use the \ tag before and after to use proper formatting in fixed font.
    The output from DBMS_XPLAN.DISPLAY shows very nicely the partitions accessed, so it might be helpful to identify if and what kind of partition pruning applies.
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

  • Partition Eliminiation on views and joins with other partitioned tables

    I have a bunch of tables that are daily partioned and other which are not. We constantly join all these tables. I have noticed that partition elimination doesn't happen in most cases and I want some input or pointers on these.
    Case 1
    We have a view that joins a couple of partitioned tables on the id fileds and they the partition key is timestamp with local time zone.
    TABLEA
    tableaid
    atime
    TABLEB
    tablebid
    tableaid
    btime
    The view basically joins on tableaid, a.tableaid = b.tableaid(+) and a bunch of other non partitioned tables. atime and btime are the individal partition keys in the tables and these time do not match up like the id's in other words there is a little bit of correlation but they can be very different.
    When I run a query against the view providing a time range for btime, I see partition elimination on tabled in the explain plan with KEY on Pstart/Pstop. But its a full tablescan on tablea. I was hoping there would be somekind of partition elimination here since its also partioned daily on the same datatype timestamp with local time zone.
    Case 2
    I have a couple of more partitioned tables
    TABELC
    tablecid
    tablebid
    ctime
    TABLED
    tabledid
    tablebid
    dtime
    As you can see these tables are joined with tablebid and the times here generally correlate to tableb's timestamp as well.
    Sub Case 1
    When I join these tables to the view and give a time range on btime, I see partition elimination happening on tableb but not on tablea or any of the other tables.
    Sub Case 2
    Then I got rid of the view, wrote a query that us similar to the view where I join on tableaid (tablea and tableb), then on tablebid (tableb, tablec and tabled) and a few other tables and execute the query with some time range on btime and I still see that partition elimination happens only on tableb.
    I thought that if other tables are also partitioned on a similark key that partition eliminition should happen? Or what am I missing here that is preventing from partition elimination on the other tables.

    Performance is of utmost importance and partition pruning is going to help in that. I guess that's what I'm trying to acheive.
    To achive partition elimination on tablec, d, etc I'm doing an outer join with btime and that seems to work. Also since most of the time after the partition elimination, I don't need a full tablescan since the period I will be querying most of the time will be small I also created a local index on id field that I'm using to join so that it can do a "TABLE ACCESS BY LOCAL INDEX ROWID" this way it should peform better than a global index since the index traversal path should be small when compared to the global index.
    Of couse I still have problem with the tablea not being pruned, since I cannot do an outer join on two fields in the same table (id and time). So might just include the time criteria again and may be increase the time range a little more when compared to what the actual user submitted to try not to miss those rows.
    Any suggestions is always welcome.

  • Partition Pruning on Interval Range Partitioned Table not happening when SYSDATE used in Where Clause

    We have tables that are interval range partitioned on a DATE column, with a partition for each day - all very standard and straight out of Oracle doc.
    A 3rd party application queries the tables to find number of rows based on date range that is on the column used for the partition key.
    This application uses date range specified relative to current date - i.e. for last two days would be "..startdate > SYSDATE -2 " - but partition pruning does not take place and the explain plan shows that every partition is included.
    By presenting the query using the date in a variable partition pruning does table place, and query obviously performs much better.
    DB is 11.2.0.3 on RHEL6, and default parameters set - i.e. nothing changed that would influence optimizer behavior to something unusual.
    I can't work out why this would be so. It very easy to reproduce with simple test case below.
    I'd be very interested to hear any thoughts on why it is this way and whether anything can be done to permit the partition pruning to work with a query including SYSDATE as it would be difficult to get the application code changed.
    Furthermore to make a case to change the code I would need an explanation of why querying using SYSDATE is not good practice, and I don't know of any such information.
    1) Create simple partitioned table
    CREATETABLE part_test
       (id                      NUMBER NOT NULL,
        starttime               DATE NOT NULL,
        CONSTRAINT pk_part_test PRIMARY KEY (id))
    PARTITION BY RANGE (starttime) INTERVAL (NUMTODSINTERVAL(1,'day')) (PARTITION p0 VALUES LESS THAN (TO_DATE('01-01-2013','DD-MM-YYYY')));
    2) Populate table 1million rows spread between 10 partitions
    BEGIN
        FOR i IN 1..1000000
        LOOP
            INSERT INTO part_test (id, starttime) VALUES (i, SYSDATE - DBMS_RANDOM.value(low => 1, high => 10));
        END LOOP;
    END;
    EXEC dbms_stats.gather_table_stats('SUPER_CONF','PART_TEST');
    3) Query the Table for data from last 2 days using SYSDATE in clause
    EXPLAIN PLAN FOR
    SELECT  count(*)
    FROM    part_test
    WHERE   starttime >= SYSDATE - 2;
    | Id  | Operation                 | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT          |           |     1 |     8 |  7895  (1)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE           |           |     1 |     8 |            |          |       |       |
    |   2 |   PARTITION RANGE ITERATOR|           |   111K|   867K|  7895   (1)| 00:00:01 |   KEY |1048575|
    |*  3 |    TABLE ACCESS FULL      | PART_TEST |   111K|   867K|  7895   (1)| 00:00:01 |   KEY |1048575|
    Predicate Information (identified by operation id):
       3 - filter("STARTTIME">=SYSDATE@!-2)
    4) Now do the same query but with SYSDATE - 2 presented as a literal value.
    This query returns the same answer but very different cost.
    EXPLAIN PLAN FOR
    SELECT count(*)
    FROM part_test
    WHERE starttime >= (to_date('23122013:0950','DDMMYYYY:HH24MI'))-2;
    | Id  | Operation                 | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT          |           |     1 |     8 |   131  (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE           |           |     1 |     8 |            |          |       |       |
    |   2 |   PARTITION RANGE ITERATOR|           |   111K|   867K|   131   (0)| 00:00:01 |   356 |1048575|
    |*  3 |    TABLE ACCESS FULL      | PART_TEST |   111K|   867K|   131   (0)| 00:00:01 |   356 |1048575|
    Predicate Information (identified by operation id):
       3 - filter("STARTTIME">=TO_DATE(' 2013-12-21 09:50:00', 'syyyy-mm-dd hh24:mi:ss'))
    thanks in anticipation
    Jim

    As Jonathan has already pointed out there are situations where the CBO knows that partition pruning will occur but is unable to identify those partitions at parse time. The CBO will then use a dynamic pruning which means determine the partitions to eliminate dynamically at run time. This is why you see the KEY information instead of a known partition number. This is to occur mainly when you compare a function to your partition key i.e. where partition_key = function. And SYSDATE is a function. For the other bizarre PSTOP number (1048575) see this blog
    http://hourim.wordpress.com/2013/11/08/interval-partitioning-and-pstop-in-execution-plan/
    Best regards
    Mohamed Houri

  • Partition pruning, Nested loops

    Hi,
    I am having a problem with getting partition pruning in a query. I've managed to dumb down the problem to two tables and a minimal query (see below).
    Basically, I have a partitioned table "Yearly Facts", and a helper table "Current Year" that always contain 1 row. The sole purpose of this one row is to tell what the curent year is, what the previous year was and what the next year will be. (In the real problem, there are non-standard timeperiods, so one cannot just calculate previous and next by adding/subtracting 1 as would be possible in this example).
    The following query is executed the way I want.
    It performs a scan on current_year, and then nested loop into the facts. And partition pruning was happening.
    select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
      from yearly_fact_t a
          ,current_year  b
    where a.year_key = b.curr_year;
    | Id  | Operation                  | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT           |               |     1 |    39 |     4   (0)| 00:00:01 |       |    |
    |   1 |  SORT AGGREGATE            |               |     1 |    39 |            |          |       |    |
    |   2 |   NESTED LOOPS             |               |     1 |    39 |     4   (0)| 00:00:01 |       |    |
    |   3 |    INDEX FAST FULL SCAN    | SYS_C00247890 |     1 |    13 |     2   (0)| 00:00:01 |       |    |
    |   4 |    PARTITION RANGE ITERATOR|               |     1 |    26 |     2   (0)| 00:00:01 |   KEY |   KEY |
    |*  5 |     TABLE ACCESS FULL      | YEARLY_FACT_T |     1 |    26 |     2   (0)| 00:00:01 |   KEY |   KEY |
    Predicate Information (identified by operation id):
       5 - filter("A"."YEAR_KEY"="B"."CURR_YEAR")The following query is where I have my problem.
    The basic xplan is the same, but for some reason the cbo gave up and decide to scan all partitions, which was not very scalable on production data :)
    I would have thought that the plan would be the same.
    select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
          ,sum(decode(a.year_key, b.prev_year, some_measure)) as prev_year_measure
      from yearly_fact_t a
          ,current_year  b
    where a.year_key = b.curr_year
        or a.year_key = b.prev_year;
    | Id  | Operation             | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT      |               |     1 |    52 |    13   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE       |               |     1 |    52 |            |          |       |       |
    |   2 |   NESTED LOOPS        |               |     4 |   208 |    13   (0)| 00:00:01 |       |       |
    |   3 |    TABLE ACCESS FULL  | CURRENT_YEAR  |     1 |    26 |     4   (0)| 00:00:01 |       |       |
    |   4 |    PARTITION RANGE ALL|               |     4 |   104 |     9   (0)| 00:00:01 |     1 |     6 |
    |*  5 |     TABLE ACCESS FULL | YEARLY_FACT_T |     4 |   104 |     9   (0)| 00:00:01 |     1 |     6 |
    Predicate Information (identified by operation id):
       5 - filter("A"."YEAR_KEY"="B"."CURR_YEAR" OR "A"."YEAR_KEY"="B"."PREV_YEAR")
    -- drop table yearly_fact_t purge;
    -- drop table current_year  purge;
    create table current_year(
       curr_year number(4) not null
      ,prev_year number(4) not null
      ,next_year number(4) not null
      ,primary key(curr_year)
      ,unique(prev_year)
      ,unique(next_year)
    insert into current_year(curr_year, prev_year, next_year) values(2010, 2009, 2011);
    commit;
    create table yearly_fact_t(
       year_key     number(4) not null
      ,some_dim_key number    not null
      ,some_measure number    not null
    partition by range(year_key)(
       partition p2007 values less than(2008)
      ,partition p2008 values less than(2009)
      ,partition p2009 values less than(2010)
      ,partition p2010 values less than(2011)
      ,partition p2011 values less than(2012) 
      ,partition pmax  values less than(maxvalue)
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2007,1, 10);
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2008,1, 20);
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2009,1, 30);
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2010,1, 40);
    commit; What can I do to get partition pruning to happen in the second query?
    Or even better, what is it in my query that prevents it from happening?
    We're running Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit.
    Best regards
    Ronnie

    Hi Ronnie,
    Check whether your statistics are up to date.
    SQL> set autotrace traceonly exp
    SQL> select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
      2        ,sum(decode(a.year_key, b.prev_year, some_measure)) as prev_year_measure
      3    from yearly_fact_t a
      4        ,current_year  b
      5   where a.year_key = b.curr_year
      6      or a.year_key = b.prev_year;
    Execution Plan
    Plan hash value: 229094315
    | Id  | Operation             | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT      |               |     1 |    52 |    10   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE       |               |     1 |    52 |            |          |       |       |
    |   2 |   NESTED LOOPS        |               |     4 |   208 |    10   (0)| 00:00:01 |       |       |
    |   3 |    TABLE ACCESS FULL  | CURRENT_YEAR  |     1 |    26 |     3   (0)| 00:00:01 |       |       |
    |   4 |    PARTITION RANGE ALL|               |     4 |   104 |     7   (0)| 00:00:01 |     1 |     6 |
    |*  5 |     TABLE ACCESS FULL | YEARLY_FACT_T |     4 |   104 |     7   (0)| 00:00:01 |     1 |     6 |
    Predicate Information (identified by operation id):
       5 - filter("A"."YEAR_KEY"="B"."CURR_YEAR" OR "A"."YEAR_KEY"="B"."PREV_YEAR")
    Note
       - dynamic sampling used for this statement
    SQL> set autotrace off
    SQL> exec dbms_stats.gather_table_stats(user, 'current_year', estimate_percent=>100, cascade=>true, method_opt
    =>'for all columns size 1');
    PL/SQL procedure successfully completed.
    SQL>
    SQL> exec dbms_stats.gather_table_stats(user, 'yearly_fact_t', estimate_percent=>100, cascade=>true, method_op
    t=>'for all columns size 1');
    PL/SQL procedure successfully completed.
    SQL> set autotrace traceonly exp
    SQL> select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
      2        ,sum(decode(a.year_key, b.prev_year, some_measure)) as prev_year_measure
      3    from yearly_fact_t a
      4        ,current_year  b
      5   where a.year_key = b.curr_year
      6      or a.year_key = b.prev_year;
    Execution Plan
    Plan hash value: 2253546831
    | Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT            |               |     1 |    15 |     8   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE             |               |     1 |    15 |            |          |       |       |
    |   2 |   CONCATENATION             |               |       |       |            |          |       |       |
    |   3 |    NESTED LOOPS             |               |     1 |    15 |     4   (0)| 00:00:01 |       |       |
    |   4 |     TABLE ACCESS FULL       | CURRENT_YEAR  |     1 |     8 |     3   (0)| 00:00:01 |       |       |
    |   5 |     PARTITION RANGE ITERATOR|               |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    |*  6 |      TABLE ACCESS FULL      | YEARLY_FACT_T |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    |   7 |    NESTED LOOPS             |               |     1 |    15 |     4   (0)| 00:00:01 |       |       |
    |   8 |     TABLE ACCESS FULL       | CURRENT_YEAR  |     1 |     8 |     3   (0)| 00:00:01 |       |       |
    |   9 |     PARTITION RANGE ITERATOR|               |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    |* 10 |      TABLE ACCESS FULL      | YEARLY_FACT_T |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    Predicate Information (identified by operation id):
       6 - filter("A"."YEAR_KEY"="B"."PREV_YEAR")
      10 - filter("A"."YEAR_KEY"="B"."CURR_YEAR" AND LNNVL("A"."YEAR_KEY"="B"."PREV_YEAR"))
    SQL> set autotrace off
    SQL>Asif Momen
    http://momendba.blogspot.com

  • Hash partitions+pruning+star transformation

    Hi there,
    We are considering partitioning our fact table on product_id (hash) range and list not suitable for us, most queries by product.
    Couple of questions
    1) does oracle create the hash partitions automaticall, if say hash by quantity what happens if later decide need more partitions - keen to keep maintenance to minimum
    2) Will partition pruning work
    simplified structure of fact table
    sales_qty
    product_id
    customer_id
    day_id (date of sale)
    simple query
    select sum(sale_qty)
    from sales, products, customers
    where sales.product_id = product.product_id
    and sales.customer_id = customer.customer_id
    and product.creation_week between 200901 and 200952
    all id's in the fact table are surrogate id's and are simply the dimesnion keys of the realetd dimensions, therefore users won't query omn these columns directly.
    If we hash partition on product_id and database parameter star_transformation enabled will this give us query performance benefits (i.e. partition pruning).
    Many Thanks

    Hi there,
    We are considering partitioning our fact table on product_id (hash) range and list not suitable for us, most queries by product.
    Couple of questions
    1) does oracle create the hash partitions automaticall, if say hash by quantity what happens if later decide need more partitions - keen to keep maintenance to minimum
    2) Will partition pruning work
    simplified structure of fact table
    sales_qty
    product_id
    customer_id
    day_id (date of sale)
    simple query
    select sum(sale_qty)
    from sales, products, customers
    where sales.product_id = product.product_id
    and sales.customer_id = customer.customer_id
    and product.creation_week between 200901 and 200952
    all id's in the fact table are surrogate id's and are simply the dimesnion keys of the realetd dimensions, therefore users won't query omn these columns directly.
    If we hash partition on product_id and database parameter star_transformation enabled will this give us query performance benefits (i.e. partition pruning).
    Many Thanks

Maybe you are looking for

  • Blue Screen when connecting iPod Touch -

    Hello, unfortunately I have no points to reward an answer. Still, I get my chance to get one from a friendly and understanding person. The iPod Touch is a "September edition" with firmware 1.1.4 (4A102) lately updated. Whenever I connect he iPod, my

  • Flaky Keyboard Issues

    Occasionally, when I wake my iBook from sleeping, the keyboard won't respond to anything I type. I have to put it back to sleep, and wake it again. If I'm lucky, the keyboard will then work. If I'm not, it takes several sleep/wake cycles to get the k

  • Do I have a Screw Loose - or is it in my mind?

    Hi Just bought a used Mac yesterday and after fixing disconnected fans with the help of maclover I noticed there might be a screw missing from where the metal cover over the CPUs slips in just below the case (I hope thats clear enough). Maybe I shoul

  • 10.5 server: could not reliably determine the server´s fully qualified doma

    I bought mac 10.5 server unlimited clientes, yesterday I tried to install the software 3 times and never worked (from basic to advanced apple preconfigurations). I had the carrier support yesterday to verify that it is not a problem of the link. the

  • XlWebApp location

    hi experts ! i am trying to make some changes in xlWebApp.war but i am unable to find the appropriate war file to update. i have deployed OIM on weblogic 10.3. now there are three places where i can find this war file i.e [OIM_DIR]\oracle\xellerate\W