CBO + View

Hi all.
So, I get many servers with Oracle 9208 + SLES 9.4
I have view :
CREATE OR REPLACE FORCE VIEW SA.V_FULL_DSPEC
(ID, DOCUMENT_ID, DEPTFR_ID, DEPTTO_ID, ARTICLE_ID,
INCLUDE_ID, QTY, SALE_PRICE, BOSS_PRICE, PRICE,
ORDER_NUM, QTY_REAL, PRICE_TYPE, BOSS_PRICE_TYPE, EXT_CODE,
QTY_REAL_CONFIRM, PACKAGE_ID, VAT_ID)
AS
SELECT /*+ INDEX (E_DSPEC) */
ID
,Document_id
,Deptfr_id
,Deptto_id
,Article_id
,Include_id
,Qty
,Sale_price
,Boss_price
,Price
,Order_num
,Qty_real
,Price_type
,Boss_price_type
,Ext_code
,qty_real_confirm
,package_id
,vat_id
FROM E_dspec
UNION ALL
SELECT /*+ INDEX (ARC_DSPEC) */
ID
,Document_id
,Deptfr_id
,Deptto_id
,Article_id
,Include_id
,Qty
,Sale_price
,Boss_price
,Price
,Order_num
,Qty_real
,Price_type
,Boss_price_type
,Ext_code
,qty_real_confirm
,package_id
,vat_id
FROM Arc_dspec;
Each table have more than 1 milion rows.
And have some query, that using this view.
So, I have srvers 2 groups : A and B
On server group A I have one execution plan of this query
On server group B I have other execution plan of this query, not like on server group A.
Difference between plans are wery big
If I change table sequence in view for server group B, i've get plan like on group A
But if I change table sequence in view for server group A, plan don't change.
Performance of query on server group A good, on server group B bad ((
Query do not change on any server group.
I can't understand, that the change of sequence can change the plan?
If you need more info, tel me.
server group A Execution Plan
0     SELECT STATEMENT Optimizer=CHOOSE (Cost=114438 Card=1 Bytes=263)
1     0 NESTED LOOPS (Cost=2 Card=1 Bytes=25)
2     1 TABLE ACCESS (BY INDEX ROWID) OF 'L_INCLUDE' (Cost=1 Card=1 Bytes=16)
3     2     INDEX (RANGE SCAN) OF 'I_LINCLUDE_ARTICLEID' (NON-UNIQUE) (Cost=3 Card=1)
4     1 TABLE ACCESS (BY INDEX ROWID) OF 'D_INCLUDE' (Cost=1 Card=1 Bytes=9)
5     4     INDEX (UNIQUE SCAN) OF 'PK_D_INCLUDE' (UNIQUE)
6     0 SORT (ORDER BY) (Cost=114438 Card=1 Bytes=263)
7     6 SORT (GROUP BY) (Cost=114438 Card=1 Bytes=263)
8     7     FILTER
9     8     NESTED LOOPS (Cost=114404 Card=1 Bytes=263)
10     9     MERGE JOIN (CARTESIAN) (Cost=114403 Card=1 Bytes=189)
11 10     NESTED LOOPS (Cost=114402 Card=1 Bytes=185)
12 11          NESTED LOOPS (Cost=114145 Card=5 Bytes=660)
13 12          NESTED LOOPS (Cost=2 Card=1 Bytes=99)
14 13          TABLE ACCESS (BY INDEX ROWID) OF 'D_DEPT' (Cost=1 Card=1 Bytes=44)
15 14          INDEX (UNIQUE SCAN) OF 'PK_D_DEPT' (UNIQUE) (Cost=1 Card=1)
16 13          TABLE ACCESS (BY INDEX ROWID) OF 'D_DEPT' (Cost=1 Card=1 Bytes=55)
17 16          INDEX (UNIQUE SCAN) OF 'PK_D_DEPT' (UNIQUE)
18 12          VIEW OF 'V_FULL_DHEAD' (Cost=114143 Card=5 Bytes=165)
19 18          UNION-ALL
20 19          FILTER
21 20               TABLE ACCESS (BY INDEX ROWID) OF 'E_DHEAD' (Cost=11 Card=2 Bytes=48)
22 21               INDEX (RANGE SCAN) OF 'IDX_E_DHEAD_DOC_DATE' (NON-UNIQUE) (Cost=6 Card=776)
23 19          FILTER
24 23               PARTITION RANGE (ITERATOR)
25 24               PARTITION LIST (INLIST)
26 25               TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'ARC_DHEAD' (Cost=1012 Card=34150 Bytes=819600)
27 26               INDEX (RANGE SCAN) OF 'I_AHEAD_DOC_DATE_' (NON-UNIQUE) (Cost=793 Card=184412)
28 11          VIEW OF 'V_FULL_DSPEC' (Cost=52 Card=1 Bytes=53)
29 28          UNION-ALL (PARTITION)
30 29          TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'ARC_DSPEC' (Cost=1 Card=1 Bytes=27)
31 30          INDEX (RANGE SCAN) OF 'I_ADSPEC_DOCUMENT_ID' (NON-UNIQUE) (Cost=4 Card=6)
32 29          TABLE ACCESS (BY INDEX ROWID) OF 'E_DSPEC' (Cost=1 Card=1 Bytes=27)
33 32          INDEX (RANGE SCAN) OF 'I_DSPEC_DOCUMENT_ID' (NON-UNIQUE) (Cost=3 Card=9)
34 10     BUFFER (SORT) (Cost=114351 Card=4 Bytes=16)
35 34          INDEX (RANGE SCAN) OF 'DEPT_FIRM_FK2' (NON-UNIQUE)
36     9     TABLE ACCESS (BY INDEX ROWID) OF 'D_ARTICLE' (Cost=1 Card=1 Bytes=74)
37 36     INDEX (UNIQUE SCAN) OF 'D_ARTICLE_PK' (UNIQUE)
38 36     TABLE ACCESS (BY INDEX ROWID) OF 'D_ARTICLE' (Cost=1 Card=1 Bytes=26)
39 38          INDEX (UNIQUE SCAN) OF 'D_ARTICLE_PK' (UNIQUE) (Cost=2 Card=1)
40 39          TABLE ACCESS (FULL) OF 'DUAL' (Cost=2 Card=82)
41 36     TABLE ACCESS (BY INDEX ROWID) OF 'D_ARTICLE' (Cost=1 Card=1 Bytes=26)
42 41          INDEX (UNIQUE SCAN) OF 'D_ARTICLE_PK' (UNIQUE) (Cost=2 Card=1)
43 42          TABLE ACCESS (FULL) OF 'DUAL' (Cost=2 Card=82)
server group B Execution Plan
0     SELECT STATEMENT Optimizer=CHOOSE (Cost=1259 Card=1 Bytes=259)
1     0 NESTED LOOPS (Cost=2 Card=1 Bytes=25)
2     1 TABLE ACCESS (BY INDEX ROWID) OF 'L_INCLUDE' (Cost=1 Card=1 Bytes=16)
3     2     INDEX (RANGE SCAN) OF 'I_LINCLUDE_ARTICLEID' (NON-UNIQUE) (Cost=3 Card=1)
4     1 TABLE ACCESS (BY INDEX ROWID) OF 'D_INCLUDE' (Cost=1 Card=1 Bytes=9)
5     4     INDEX (UNIQUE SCAN) OF 'PK_D_INCLUDE' (UNIQUE)
6     0 SORT (ORDER BY) (Cost=1259 Card=1 Bytes=259)
7     6 SORT (GROUP BY) (Cost=1259 Card=1 Bytes=259)
8     7     FILTER
9     8     MERGE JOIN (CARTESIAN) (Cost=1242 Card=1 Bytes=259)
10     9     NESTED LOOPS (Cost=1241 Card=1 Bytes=255)
11 10     NESTED LOOPS (Cost=1203 Card=383 Bytes=85026)
12 11          NESTED LOOPS (Cost=1024 Card=1787 Bytes=302003)
13 12          NESTED LOOPS (Cost=2 Card=1 Bytes=95)
14 13          TABLE ACCESS (BY INDEX ROWID) OF 'D_DEPT' (Cost=1 Card=1 Bytes=42)
15 14          INDEX (UNIQUE SCAN) OF 'PK_D_DEPT' (UNIQUE) (Cost=1 Card=1)
16 13          TABLE ACCESS (BY INDEX ROWID) OF 'D_DEPT' (Cost=1 Card=1 Bytes=53)
17 16          INDEX (UNIQUE SCAN) OF 'PK_D_DEPT' (UNIQUE)
18 12          TABLE ACCESS (FULL) OF 'D_ARTICLE' (Cost=1022 Card=1787 Bytes=132238)
19 18          TABLE ACCESS (BY INDEX ROWID) OF 'D_ARTICLE' (Cost=1 Card=1 Bytes=26)
20 19          INDEX (UNIQUE SCAN) OF 'D_ARTICLE_PK' (UNIQUE) (Cost=2 Card=1)
21 20               TABLE ACCESS (FULL) OF 'DUAL' (Cost=11 Card=8168)
22 18          TABLE ACCESS (BY INDEX ROWID) OF 'D_ARTICLE' (Cost=1 Card=1 Bytes=26)
23 22          INDEX (UNIQUE SCAN) OF 'D_ARTICLE_PK' (UNIQUE) (Cost=2 Card=1)
24 23               TABLE ACCESS (FULL) OF 'DUAL' (Cost=11 Card=8168)
25 11          VIEW OF 'V_FULL_DSPEC' (Cost=1 Card=1 Bytes=53)
26 25          UNION-ALL (PARTITION)
27 26          TABLE ACCESS (BY INDEX ROWID) OF 'E_DSPEC' (Cost=1 Card=1 Bytes=28)
28 27          INDEX (RANGE SCAN) OF 'I_DSPEC_ARTICLE_ID' (NON-UNIQUE) (Cost=1 Card=16)
29 26          PARTITION RANGE (ALL)
30 29          PARTITION LIST (ALL)
31 30               TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'ARC_DSPEC' (Cost=50 Card=1 Bytes=27)
32 31               INDEX (RANGE SCAN) OF 'I_ASPEC_ARTICLE_ID' (NON-UNIQUE) (Cost=82 Card=528)
33 10     VIEW OF 'V_FULL_DHEAD' (Cost=1 Card=1 Bytes=33)
34 33          UNION-ALL (PARTITION)
35 34          FILTER
36 35          TABLE ACCESS (BY INDEX ROWID) OF 'E_DHEAD' (Cost=1 Card=1 Bytes=24)
37 36          INDEX (UNIQUE SCAN) OF 'PK_E_DHEAD' (UNIQUE) (Cost=1 Card=1)
38 34          FILTER
39 38          TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'ARC_DHEAD' (Cost=1 Card=1 Bytes=24)
40 39          INDEX (UNIQUE SCAN) OF 'I_ARC_HEAD_ID' (UNIQUE) (Cost=2 Card=1)
41     9     BUFFER (SORT) (Cost=1258 Card=4 Bytes=16)
42 41     INDEX (RANGE SCAN) OF 'UK_L_DEPT_FIRM' (NON-UNIQUE) (Cost=1 Card=4 Bytes=16)

The amount of data on both server group are close and same.
Statistic gather every day, with dbms_stats.gather_schema_stats(); on each server (group A and B) And dba_tables view show that the statistic have been gathered.
I have try to use hints but get another plan from group server A. And all this plan are very slow to, like on server group B.
I try to experement with session parameter:
OPTIMIZER_INDEX_COST_ADJ
OPTIMIZER_INDEX_CACHING
DB_FILE_MULTIBLOCK_READ_COUNT
SORT_AREA_SIZE
But no one of them didn't change the plan on server group B (i don't use stored outlines)
So why? I have same Oracle, same OS, same DB and clase data, but plan is not the same...
Edited by: HuliGUN on 19.07.2010 23:01
Edited by: HuliGUN on 19.07.2010 23:10

Similar Messages

  • View joining two spatial tables and strange CBO behaviour

    Hi all,
    I've following view in my database:
    CREATE OR REPLACE VIEW my_view AS
    SELECT id, 'table1' AS source, location FROM my_table1
    UNION ALL
    SELECT id, 'table2' AS source, location FROM my_table2;
    When I execute query:
    SELECT * FROM my_view WHERE SDO_RELATE(location, SDO_GEOMETRY(...), 'mask=anyinteract') = 'TRUE';
    It works as expected.
    When running query like (getting location with subquery):
    SELECT * FROM my_view WHERE SDO_RELATE(location, (SELECT location FROM my_table3 WHERE id = 123, 'mask=anyinteract') = 'TRUE';
    It doesn't work. Oracle Throws "DatabaseError: ORA-13226: interface not supported without a spatial index"
    Further investigation revealed strange behaviour of CBO:
    In first case Oracle CBO uses Spatial index just fine and as expected.
    But second query and CBO get's a bit strange - unique index scan is used for subselect, but for view tables is full table scan is used and SDO_RELATE is not happy with that since no spatial index is used.
    How I can use spatial indexes regardless of that subselect?

    Hi folks,
    Looking over these responses and not finding a lot of clarity yet in terms of leaving a trail for future readers to glean an answer from.  I was just looking through the back-and-forth and curious myself about the issue  First of all I think Jani's observations are quite on target.  This CBO reaction is weird and does not work they way most Oracle users would expect it to work.  Secondly, Jani really should tell us his Oracle version and folks providing answers should as well - the CBO is always being tweaked.  Thirdly, Stefan provides a solution though it's a rather expensive solution to my taste.  And finally, I think we as a group need to spend a bit more time reproducing things in code.  I will give it a shot, feel free to correct anything I got wrong.
    So first of all, I wrote this up quick on 12.1.0.2 and verified it was the same on 11.2.0.4
    DROP TABLE my_table1 PURGE;
    CREATE TABLE my_table1(
        objectid INTEGER NOT NULL
       ,tsource  VARCHAR2(30 Char)
       ,shape    MDSYS.SDO_GEOMETRY
       ,PRIMARY KEY(objectid)
    DROP TABLE my_table2 PURGE;
    CREATE TABLE my_table2(
        objectid INTEGER NOT NULL
       ,tsource  VARCHAR2(30 Char)
       ,shape    MDSYS.SDO_GEOMETRY
       ,PRIMARY KEY(objectid)
    DROP TABLE my_table3 PURGE;
    CREATE TABLE my_table3(
        objectid INTEGER NOT NULL
       ,tsource  VARCHAR2(30 Char)
       ,shape    MDSYS.SDO_GEOMETRY
       ,PRIMARY KEY(objectid)
    CREATE OR REPLACE PROCEDURE seeder(
       p_count IN NUMBER
    AS
       sdo_foo MDSYS.SDO_GEOMETRY;
       int_counter NUMBER := 1;
       FUNCTION random_line
       RETURN MDSYS.SDO_GEOMETRY
       AS
          num_x1 NUMBER;
          num_y1 NUMBER;
          num_offx NUMBER;
          num_offy NUMBER;
       BEGIN
          num_x1 := dbms_random.value(-179,179);
          num_y1 := dbms_random.value(-89,89);
          RETURN MDSYS.SDO_GEOMETRY(
              2002
             ,8265
             ,NULL
             ,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1)
             ,MDSYS.SDO_ORDINATE_ARRAY(
                  num_x1
                 ,num_y1
                 ,num_x1 + 0.0001
                 ,num_y1 + 0.0001
       END random_line;
    BEGIN
       FOR i IN 1 .. p_count
       LOOP
          sdo_foo := random_line();
          INSERT INTO my_table1
          VALUES (
              int_counter
             ,'table1'
             ,sdo_foo
          int_counter := int_counter + 1;
          sdo_foo := random_line();
          INSERT INTO my_table2
          VALUES (
              int_counter
             ,'table2'
             ,sdo_foo
          int_counter := int_counter + 1;
          sdo_foo := random_line();
          INSERT INTO my_table3
          VALUES (
              int_counter
             ,'table3'
             ,sdo_foo
          int_counter := int_counter + 1;
       END LOOP;
       INSERT INTO my_table1
       VALUES (
           0
          ,'table1'
          ,MDSYS.SDO_GEOMETRY(
               2002
              ,8265
              ,NULL
              ,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1)
              ,MDSYS.SDO_ORDINATE_ARRAY(
                   -87.8211111
                  ,42.5847222
                  ,-87.8212
                  ,42.5848
       INSERT INTO my_table3
       VALUES (
           0
          ,'table3'
          ,MDSYS.SDO_GEOMETRY(
               2002
              ,8265
              ,NULL
              ,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1)
              ,MDSYS.SDO_ORDINATE_ARRAY(
                   -87.8211111
                  ,42.5848
                  ,-87.8212
                  ,42.5847222
       COMMIT;
    END seeder;
    BEGIN
       seeder(100000);
    END;
    SELECT 'my_table1: ' || COUNT(*) AS invalid_count FROM my_table1 WHERE MDSYS.SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(shape,0.05) <> 'TRUE'
    UNION ALL
    SELECT 'my_table2: ' || COUNT(*) AS invalid_count FROM my_table2 WHERE MDSYS.SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(shape,0.05) <> 'TRUE'
    UNION ALL
    SELECT 'my_table3: ' || COUNT(*) AS invalid_count FROM my_table3 WHERE MDSYS.SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(shape,0.05) <> 'TRUE';
    BEGIN
       INSERT INTO user_sdo_geom_metadata(
           table_name
          ,column_name
          ,diminfo
          ,srid
       ) VALUES (
           'MY_TABLE1'
          ,'SHAPE'
          ,MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-180,180,.05),MDSYS.SDO_DIM_ELEMENT('Y',-90,90,.05))
          ,8265
       COMMIT;
    EXCEPTION
       WHEN OTHERS
       THEN
          NULL;
    END;
    BEGIN
       INSERT INTO user_sdo_geom_metadata(
           table_name
          ,column_name
          ,diminfo
          ,srid
       ) VALUES (
           'MY_TABLE2'
          ,'SHAPE'
          ,MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-180,180,.05),MDSYS.SDO_DIM_ELEMENT('Y',-90,90,.05))
          ,8265
       COMMIT;
    EXCEPTION
       WHEN OTHERS
       THEN
          NULL;
    END;
    BEGIN
       INSERT INTO user_sdo_geom_metadata(
           table_name
          ,column_name
          ,diminfo
          ,srid
       ) VALUES (
           'MY_TABLE3'
          ,'SHAPE'
          ,MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-180,180,.05),MDSYS.SDO_DIM_ELEMENT('Y',-90,90,.05))
          ,8265
       COMMIT;
    EXCEPTION
       WHEN OTHERS
       THEN
          NULL;
    END;
    CREATE INDEX my_table1_spx ON my_table1
    (shape)
    INDEXTYPE IS MDSYS.SPATIAL_INDEX
    NOPARALLEL;
    CREATE INDEX my_table2_spx ON my_table2
    (shape)
    INDEXTYPE IS MDSYS.SPATIAL_INDEX
    NOPARALLEL;
    CREATE INDEX my_table3_spx ON my_table3
    (shape)
    INDEXTYPE IS MDSYS.SPATIAL_INDEX
    NOPARALLEL;
    BEGIN
       dbms_stats.gather_table_stats(USER, 'MY_TABLE1');
       dbms_stats.gather_index_stats(USER, 'MY_TABLE1_SPX');
       dbms_stats.gather_table_stats(USER, 'MY_TABLE2');
       dbms_stats.gather_index_stats(USER, 'MY_TABLE2_SPX');
       dbms_stats.gather_table_stats(USER, 'MY_TABLE3');
       dbms_stats.gather_index_stats(USER, 'MY_TABLE3_SPX');
    END;
    CREATE OR REPLACE VIEW my_view
    AS
    SELECT
    objectid
    ,'table1' AS tsource
    ,shape
    FROM
    my_table1
    UNION ALL
    SELECT
    objectid
    ,'table2' AS tsource
    ,shape
    FROM my_table2;
    set timing on;
    -- QUERY #1
    -- Jani's original setup, works as expected
    SELECT
    COUNT(*) AS single_geom_counter
    FROM
    my_view a
    WHERE
    MDSYS.SDO_RELATE(
        a.shape
       ,MDSYS.SDO_GEOMETRY(
            2002
           ,8265
           ,NULL
           ,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1)
           ,MDSYS.SDO_ORDINATE_ARRAY(
                -87.8211111
               ,42.5848
               ,-87.8212
               ,42.5847222
       ,'mask=anyinteract'
    ) = 'TRUE';
    -- QUERY #2
    -- Now the problem statement
    SELECT
    COUNT(*) AS table_problem_counter
    FROM
    my_view a
    WHERE
    MDSYS.SDO_RELATE(
        a.shape
       ,(SELECT b.shape FROM my_table3 b WHERE b.objectid = 0)
       ,'mask=anyinteract'
    ) = 'TRUE';
    -- QUERY #3
    -- Stefan's solution
    SELECT  /*+ ORDERED */
    COUNT(*) AS stefans_solution
    FROM
    my_table3 a
    ,my_view b
    WHERE
    a.objectid = 0
    AND MDSYS.SDO_RELATE(
        a.shape
       ,b.shape
       ,'mask=anyinteract'
    ) = 'TRUE';
    Anyhow, so the hard coded query #1 that Jani provided works exactly the way most folks would expect, the second item in the relate is applied to each spatial index participating in the view.  I think we can agree this is what we want.
    Now when we move on to the problem, well its all goes off the rails as I think its looks to apply the spatial filter to the view itself which lacks an index (not sure really)
    So as Stefan says, you can work around this by rewriting things as query #3 does above though now its a full table scan of both tables in the view.  This is a long way performance wise from Query #1!
    So on my 12c test box
       query #1 Elapsed: 00:00:00.016
       query #3 Elapsed: 00:00:33.534
    On 11g production box
       query #1 Elapsed: 00:00:00.49
       query #3 Elapsed: 00:02:31.45   (ouch!)
    So hopefully someone else can jump in with more information on better solutions?  
    I overall tend to avoid the kind of unioned views that Jani is using here.  I have a hard time recalling why but I must have been burned similarly many years ago when I was first starting with Oracle spatial.  I tend to always want my spatial indexes right there where I can keep a grim stink eye on them.  It may be that a unioned view with multiple spatial indexes behind it might just be a bad practice better done with a materialized view?  Or maybe a lesser term?  Unprofitable practice?  fraught?  "Best if you don't do that"?
    Anyhow, I would be interested in what others have as input on the matter.
    Cheers,
    Paul

  • Using a variable in a view?

    I know that it may not be possible to use a variable within a view, but I'm wondering if there isn't a work-around? If there is a single value---pulled from another table---you wish to reuse in a view that does not use dynamic SQL, how do you do so? I've been toying around with WITH statements, but that's getting me nowhere. I'm using 11r2.
    BTW, please do not ask me the standard litany of angry-dba questions (why are you doing this? your database is f*****, RTFM, etc.), this is just for my own curiosity. :)
    Thank you
    Example for demo purposes only (I know it's not syntactically correct):
    variable var_value varchar2(30)
    begin
    select this_is_just_one_value
    int :var_value
    from tableX where column1 = 'BOB';
    end;
    select
    numerous_columns
    from tableY
    where
    column5 = :var_value;

    893968 wrote:
    BTW, please do not ask me the standard litany of angry-dba questions (why are you doing this? your database is f*****, RTFM, etc.), this is just for my own curiosity. :)Why are you doing this? your database is f*****! RTFM! Etc!! ;-)
    SQL is not a procedural language - so you cannot create a view for example that has a parameter signature. E.g. this is possible in a procedural language:
    declare
            cursor c( deptID number ) is
                    select * from emp where deptno = deptID;
    begin
            open c( 1234 ); --// open SQL cursor using a parameter/variable
            --// etc..
            close c;
    end;This is not possible using a SQL object like a view. As a view is not a procedure. So the same approach as the above using SQL (silly example, but do demonstrates the basics):
    // define
    create or replace view emp_view as select * from emp;
    // use
    select * from emp_view where deptno = 1234;The CBO is clever - and it will likely push such a predicate into the emp_view SQL statement.
    To parameterise such a view, is ugly. And should only be considered when dealing with issues such as security and data restrictions. A context is created - this can contain a number of name-values. The view can then use a name-value from the context. Oracle's data dictionary views use this approach.

  • CBO generating different plans for the same data in similar Environments

    Hi All
    I have been trying to compare an SQL from 2 different but similar environments build of the same hardware specs .The issue I am facing is environment A, the query executes in less than 2 minutes with plan mostly showing full table scans and hash join whereas in environment B(problematic), it times out after 2 hours with an error of unable to extend table space . The statistics are up to date in both environments for both tables and indexes . System parameters are exactly similar(default oracle for except for multiblock_read_count ).
    Both Environment have same db parameter for db_file_multiblock_read_count(16), optimizer(refer below),hash_area_size (131072),pga_aggregate_target(1G),db_block_size(8192) etc . SREADTIM, MREADTIM, CPUSPEED, MBRC are all null in aux_stats in both environment because workload was never collected i believe.
    Attached is details about the SQL with table stats, SQL and index stats my main concern is CBO generating different plans for the similar data and statistics and same hardware and software specs. Is there any thing else I should consider .I generally see environment B being very slow and always plans tend to nested loops and index scan whereas what we really need is a sensible FTS in many cases. One of the very surprising thing is METER_CONFIG_HEADER below which has just 80 blocks of data is being asked for index scan.
    show parameter optimizer
    optimizer_dynamic_sampling integer 2
    optimizer_features_enable string 10.2.0.4
    optimizer_index_caching integer 0
    optimizer_index_cost_adj integer 100
    optimizer_mode string ALL_ROWS
    optimizer_secure_view_merging boolean TRUE
    **Environment**
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
    PL/SQL Release 10.2.0.4.0 - Production
    CORE     10.2.0.4.0     Production
    TNS for Solaris: Version 10.2.0.4.0 - Production
    NLSRTL Version 10.2.0.4.0 - Production
    Note: : There are slight difference in the no of records in the attached sheet.However, I wanted to tell that i have tested with exact same data and was getting similar results but I couldn't retain the data untill collecting the details in the attachment
    TEST1     COMPARE TABLE LEVE STATS  used by CBO          
    ENVIRONMENT A
    TABLE_NAME     NUM_ROWS     BLOCKS     LAST_ANALYZED
    ASSET     3607425     167760     5/02/2013 22:11
    METER_CONFIG_HEADER     3658     80     5/01/2013 0:07
    METER_CONFIG_ITEM     32310     496     5/01/2013 0:07
    NMI     1899024     33557     18/02/2013 10:55
    REGISTER     4830153     101504     18/02/2013 9:57
    SDP_LOGICAL_ASSET     1607456     19137     18/02/2013 15:48
    SDP_LOGICAL_REGISTER     5110781     78691     18/02/2013 9:56
    SERVICE_DELIVERY_POINT     1425890     42468     18/02/2013 13:54
    ENVIRONMENT B
    TABLE_NAME     NUM_ROWS     BLOCKS     LAST_ANALYZED
    ASSET     4133939     198570     16/02/2013 10:02
    METER_CONFIG_HEADER     3779     80     16/02/2013 10:55
    METER_CONFIG_ITEM     33720     510     16/02/2013 10:55
    NMI     1969000     33113     16/02/2013 10:58
    REGISTER     5837874     120104     16/02/2013 11:05
    SDP_LOGICAL_ASSET     1788152     22325     16/02/2013 11:06
    SDP_LOGICAL_REGISTER     6101934     91088     16/02/2013 11:07
    SERVICE_DELIVERY_POINT     1447589     43804     16/02/2013 11:11
    TEST ITEM 2     COMPARE INDEX STATS  used by CBO          
    ENVIRONMENT A
    TABLE_NAME     INDEX_NAME     UNIQUENESS     BLEVEL     LEAF_BLOCKS     DISTINCT_KEYS     AVG_LEAF_BLOCKS_PER_KEY     AVG_DATA_BLOCKS_PER_KEY     CLUSTERING_FACTOR     NUM_ROWS
    ASSET     IDX_AST_DEVICE_CATEGORY_SK     NONUNIQUE     2     9878     67     147     12982     869801     3553095
    ASSET     IDX_A_SAPINTLOGDEV_SK     NONUNIQUE     2     7291     2747     2     639     1755977     3597916
    ASSET     SYS_C00102592     UNIQUE     2     12488     3733831     1     1     3726639     3733831
    METER_CONFIG_HEADER     SYS_C0092052     UNIQUE     1     12     3670     1     1     3590     3670
    METER_CONFIG_ITEM     SYS_C0092074     UNIQUE     1     104     32310     1     1     32132     32310
    NMI     IDX_NMI_ID     NONUNIQUE     2     6298     844853     1     2     1964769     1965029
    NMI     IDX_NMI_ID_NK     NONUNIQUE     2     6701     1923072     1     1     1922831     1923084
    NMI     IDX_NMI_STATS     NONUNIQUE     1     106     4     26     52     211     211
    REGISTER     REG_EFFECTIVE_DTM     NONUNIQUE     2     12498     795     15     2899     2304831     4711808
    REGISTER     SYS_C00102653     UNIQUE     2     16942     5065660     1     1     5056855     5065660
    SDP_LOGICAL_ASSET     IDX_SLA_SAPINTLOGDEV_SK     NONUNIQUE     2     3667     1607968     1     1     1607689     1607982
    SDP_LOGICAL_ASSET     IDX_SLA_SDP_SK     NONUNIQUE     2     3811     668727     1     2     1606204     1607982
    SDP_LOGICAL_ASSET     SYS_C00102665     UNIQUE     2     5116     1529606     1     1     1528136     1529606
    SDP_LOGICAL_REGISTER     SYS_C00102677     UNIQUE     2     17370     5193638     1     1     5193623     5193638
    SERVICE_DELIVERY_POINT     IDX_SDP_NMI_SK     NONUNIQUE     2     4406     676523     1     2     1423247     1425890
    SERVICE_DELIVERY_POINT     IDX_SDP_SAP_INT_NMI_SK     NONUNIQUE     2     7374     676523     1     2     1458238     1461108
    SERVICE_DELIVERY_POINT     SYS_C00102687     UNIQUE     2     4737     1416207     1     1     1415022     1416207
    ENVIRONMENT B
    TABLE_NAME     INDEX_NAME     UNIQUENESS     BLEVEL     LEAF_BLOCKS     DISTINCT_KEYS     AVG_LEAF_BLOCKS_PER_KEY     AVG_DATA_BLOCKS_PER_KEY     CLUSTERING_FACTOR     NUM_ROWS
    ASSET     IDX_AST_DEVICE_CATEGORY_SK     NONUNIQUE     2     8606     121     71     16428     1987833     4162257
    ASSET     IDX_A_SAPINTLOGDEV_SK     NONUNIQUE     2     8432     1780146     1     1     2048170     4162257
    ASSET     SYS_C00116157     UNIQUE     2     13597     4162263     1     1     4158759     4162263
    METER_CONFIG_HEADER     SYS_C00116570     UNIQUE     1     12     3779     1     1     3734     3779
    METER_CONFIG_ITEM     SYS_C00116592     UNIQUE     1     107     33720     1     1     33459     33720
    NMI     IDX_NMI_ID     NONUNIQUE     2     6319     683370     1     2     1970460     1971313
    NMI     IDX_NMI_ID_NK     NONUNIQUE     2     6597     1971293     1     1     1970771     1971313
    NMI     IDX_NMI_STATS     NONUNIQUE     1     98     48     2     4     196     196
    REGISTER     REG_EFFECTIVE_DTM     NONUNIQUE     2     15615     1273     12     2109     2685924     5886582
    REGISTER     SYS_C00116748     UNIQUE     2     19533     5886582     1     1     5845565     5886582
    SDP_LOGICAL_ASSET     IDX_SLA_SAPINTLOGDEV_SK     NONUNIQUE     2     4111     1795084     1     1     1758441     1795130
    SDP_LOGICAL_ASSET     IDX_SLA_SDP_SK     NONUNIQUE     2     4003     674249     1     2     1787987     1795130
    SDP_LOGICAL_ASSET     SYS_C004520     UNIQUE     2     5864     1795130     1     1     1782147     1795130
    SDP_LOGICAL_REGISTER     SYS_C004539     UNIQUE     2     20413     6152850     1     1     6073059     6152850
    SERVICE_DELIVERY_POINT     IDX_SDP_NMI_SK     NONUNIQUE     2     3227     660649     1     2     1422572     1447803
    SERVICE_DELIVERY_POINT     IDX_SDP_SAP_INT_NMI_SK     NONUNIQUE     2     6399     646257     1     2     1346948     1349993
    SERVICE_DELIVERY_POINT     SYS_C00128706     UNIQUE     2     4643     1447946     1     1     1442796     1447946
    TEST ITEM 3     COMPARE PLANS     
    ENVIRONMENT A
    Plan hash value: 4109575732                                             
    | Id  | Operation                       | Name                   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |                                             
    |   0 | SELECT STATEMENT                |                        |    13 |  2067 |       |   135K  (2)| 00:27:05 |                                             
    |   1 |  HASH UNIQUE                    |                        |    13 |  2067 |       |   135K  (2)| 00:27:05 |                                             
    |*  2 |   HASH JOIN                     |                        |    13 |  2067 |       |   135K  (2)| 00:27:05 |                                             
    |*  3 |    HASH JOIN                    |                        |     6 |   900 |       |   135K  (2)| 00:27:04 |                                             
    |*  4 |     HASH JOIN ANTI              |                        |     1 |   137 |       |   135K  (2)| 00:27:03 |                                             
    |*  5 |      TABLE ACCESS BY INDEX ROWID| NMI                    |     1 |    22 |       |     5   (0)| 00:00:01 |                                             
    |   6 |       NESTED LOOPS              |                        |     1 |   131 |       | 95137   (2)| 00:19:02 |                                             
    |*  7 |        HASH JOIN                |                        |     1 |   109 |       | 95132   (2)| 00:19:02 |                                             
    |*  8 |         TABLE ACCESS FULL       | ASSET                  | 36074 |  1021K|       | 38553   (2)| 00:07:43 |                                             
    |*  9 |         HASH JOIN               |                        | 90361 |  7059K|  4040K| 56578   (2)| 00:11:19 |                                             
    |* 10 |          HASH JOIN              |                        | 52977 |  3414K|  2248K| 50654   (2)| 00:10:08 |                                             
    |* 11 |           HASH JOIN             |                        | 39674 |  1782K|       | 40101   (2)| 00:08:02 |                                             
    |* 12 |            TABLE ACCESS FULL    | REGISTER               | 39439 |  1232K|       | 22584   (2)| 00:04:32 |                                             
    |* 13 |            TABLE ACCESS FULL    | SDP_LOGICAL_REGISTER   |  4206K|    56M|       | 17490   (2)| 00:03:30 |                                             
    |* 14 |           TABLE ACCESS FULL     | SERVICE_DELIVERY_POINT |   675K|    12M|       |  9412   (2)| 00:01:53 |                                             
    |* 15 |          TABLE ACCESS FULL      | SDP_LOGICAL_ASSET      |  1178K|    15M|       |  4262   (2)| 00:00:52 |                                             
    |* 16 |        INDEX RANGE SCAN         | IDX_NMI_ID_NK          |     2 |       |       |     2   (0)| 00:00:01 |                                             
    |  17 |      VIEW                       |                        | 39674 |   232K|       | 40101   (2)| 00:08:02 |                                             
    |* 18 |       HASH JOIN                 |                        | 39674 |  1046K|       | 40101   (2)| 00:08:02 |                                             
    |* 19 |        TABLE ACCESS FULL        | REGISTER               | 39439 |   500K|       | 22584   (2)| 00:04:32 |                                             
    |* 20 |        TABLE ACCESS FULL        | SDP_LOGICAL_REGISTER   |  4206K|    56M|       | 17490   (2)| 00:03:30 |                                             
    |* 21 |     TABLE ACCESS FULL           | METER_CONFIG_HEADER    |  3658 | 47554 |       |    19   (0)| 00:00:01 |                                             
    |* 22 |    TABLE ACCESS FULL            | METER_CONFIG_ITEM      |  7590 | 68310 |       |   112   (2)| 00:00:02 |                                             
    Predicate Information (identified by operation id):                                             
       2 - access("METER_CONFIG_HEADER_SK"="METER_CONFIG_HEADER_SK")                                             
       3 - access("NETWORK_TARIFF_CD"="NETWORK_TARIFF_CD")                                             
       4 - access("SERVICE_DELIVERY_POINT_SK"="TMP"."SERVICE_DELIVERY_POINT_SK")                                             
       5 - filter("ROW_CURRENT_IND"='Y' AND ("NMI_STATUS_CD"='A' OR "NMI_STATUS_CD"='D'))                                             
       7 - access("ASSET_CD"="EQUIP_CD" AND "SAP_INT_LOG_DEVICE_SK"="SAP_INT_LOG_DEVICE_SK")                                             
       8 - filter("ROW_CURRENT_IND"='Y')                                             
       9 - access("SERVICE_DELIVERY_POINT_SK"="SERVICE_DELIVERY_POINT_SK")                                             
      10 - access("SERVICE_DELIVERY_POINT_SK"="SERVICE_DELIVERY_POINT_SK")                                             
      11 - access("SAP_INT_LOGICAL_REGISTER_SK"="SAP_INT_LOGICAL_REGISTER_SK")                                             
      12 - filter("REGISTER_TYPE_CD"='C' AND (SUBSTR("REGISTER_ID_CD",1,1)='4' OR                                              
                  SUBSTR("REGISTER_ID_CD",1,1)='5' OR SUBSTR("REGISTER_ID_CD",1,1)='6') AND "ROW_CURRENT_IND"='Y')                                             
      13 - filter("ROW_CURRENT_IND"='Y')                                             
      14 - filter("ROW_CURRENT_IND"='Y')                                             
      15 - filter("ROW_CURRENT_IND"='Y')                                             
      16 - access("NMI_SK"="NMI_SK")                                             
      18 - access("SAP_INT_LOGICAL_REGISTER_SK"="SAP_INT_LOGICAL_REGISTER_SK")                                             
      19 - filter("REGISTER_TYPE_CD"='C' AND (SUBSTR("REGISTER_ID_CD",1,1)='1' OR                                              
                  SUBSTR("REGISTER_ID_CD",1,1)='2' OR SUBSTR("REGISTER_ID_CD",1,1)='3') AND "ROW_CURRENT_IND"='Y')                                             
      20 - filter("ROW_CURRENT_IND"='Y')                                             
      21 - filter("ROW_CURRENT_IND"='Y')                                             
      22 - filter("ROW_CURRENT_IND"='Y' AND "CONROL_REGISTER"='X')                                             
    ENVIRONMENT B
    Plan hash value: 2826260434                                   
    | Id  | Operation                            | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |                                   
    |   0 | SELECT STATEMENT                     |                        |     1 |   181 |   103K  (2)| 00:20:47 |                                   
    |   1 |  HASH UNIQUE                         |                        |     1 |   181 |   103K  (2)| 00:20:47 |                                   
    |*  2 |   HASH JOIN ANTI                     |                        |     1 |   181 |   103K  (2)| 00:20:47 |                                   
    |*  3 |    HASH JOIN                         |                        |     1 |   176 | 56855   (2)| 00:11:23 |                                   
    |*  4 |     HASH JOIN                        |                        |     1 |   163 | 36577   (2)| 00:07:19 |                                   
    |*  5 |      TABLE ACCESS BY INDEX ROWID     | ASSET                  |     1 |    44 |     4   (0)| 00:00:01 |                                   
    |   6 |       NESTED LOOPS                   |                        |     1 |   131 |  9834   (2)| 00:01:59 |                                   
    |   7 |        NESTED LOOPS                  |                        |     1 |    87 |  9830   (2)| 00:01:58 |                                   
    |   8 |         NESTED LOOPS                 |                        |     1 |    74 |  9825   (2)| 00:01:58 |                                   
    |*  9 |          HASH JOIN                   |                        |     1 |    52 |  9820   (2)| 00:01:58 |                                   
    |* 10 |           TABLE ACCESS BY INDEX ROWID| METER_CONFIG_HEADER    |     1 |    14 |     1   (0)| 00:00:01 |                                   
    |  11 |            NESTED LOOPS              |                        |     1 |    33 |   116   (2)| 00:00:02 |                                   
    |* 12 |             TABLE ACCESS FULL        | METER_CONFIG_ITEM      |     1 |    19 |   115   (2)| 00:00:02 |                                   
    |* 13 |             INDEX RANGE SCAN         | SYS_C00116570          |     1 |       |     1   (0)| 00:00:01 |                                   
    |* 14 |           TABLE ACCESS FULL          | SERVICE_DELIVERY_POINT |   723K|    13M|  9699   (2)| 00:01:57 |                                   
    |* 15 |          TABLE ACCESS BY INDEX ROWID | NMI                    |     1 |    22 |     5   (0)| 00:00:01 |                                   
    |* 16 |           INDEX RANGE SCAN           | IDX_NMI_ID_NK          |     2 |       |     2   (0)| 00:00:01 |                                   
    |* 17 |         TABLE ACCESS BY INDEX ROWID  | SDP_LOGICAL_ASSET      |     1 |    13 |     5   (0)| 00:00:01 |                                   
    |* 18 |          INDEX RANGE SCAN            | IDX_SLA_SDP_SK         |     2 |       |     2   (0)| 00:00:01 |                                   
    |* 19 |        INDEX RANGE SCAN              | IDX_A_SAPINTLOGDEV_SK  |     2 |       |     2   (0)| 00:00:01 |                                   
    |* 20 |      TABLE ACCESS FULL               | REGISTER               | 76113 |  2378K| 26743   (2)| 00:05:21 |                                   
    |* 21 |     TABLE ACCESS FULL                | SDP_LOGICAL_REGISTER   |  5095K|    63M| 20245   (2)| 00:04:03 |                                   
    |  22 |    VIEW                              |                        | 90889 |   443K| 47021   (2)| 00:09:25 |                                   
    |* 23 |     HASH JOIN                        |                        | 90889 |  2307K| 47021   (2)| 00:09:25 |                                   
    |* 24 |      TABLE ACCESS FULL               | REGISTER               | 76113 |   966K| 26743   (2)| 00:05:21 |                                   
    |* 25 |      TABLE ACCESS FULL               | SDP_LOGICAL_REGISTER   |  5095K|    63M| 20245   (2)| 00:04:03 |                                   
    Predicate Information (identified by operation id):                                   
       2 - access("SERVICE_DELIVERY_POINT_SK"="TMP"."SERVICE_DELIVERY_POINT_SK")                                   
       3 - access("SERVICE_DELIVERY_POINT_SK"="SERVICE_DELIVERY_POINT_SK" AND                                    
                  "SAP_INT_LOGICAL_REGISTER_SK"="SAP_INT_LOGICAL_REGISTER_SK")                                   
       4 - access("ASSET_CD"="EQUIP_CD")                                   
       5 - filter("ROW_CURRENT_IND"='Y')                                   
       9 - access("NETWORK_TARIFF_CD"="NETWORK_TARIFF_CD")                                   
      10 - filter("ROW_CURRENT_IND"='Y')                                   
      12 - filter("ROW_CURRENT_IND"='Y' AND "CONROL_REGISTER"='X')                                   
      13 - access("METER_CONFIG_HEADER_SK"="METER_CONFIG_HEADER_SK")                                   
      14 - filter("ROW_CURRENT_IND"='Y')                                   
      15 - filter("ROW_CURRENT_IND"='Y' AND ("NMI_STATUS_CD"='A' OR "NMI_STATUS_CD"='D'))                                   
      16 - access("NMI_SK"="NMI_SK")                                   
      17 - filter("ROW_CURRENT_IND"='Y')                                   
      18 - access("SERVICE_DELIVERY_POINT_SK"="SERVICE_DELIVERY_POINT_SK")                                   
      19 - access("SAP_INT_LOG_DEVICE_SK"="SAP_INT_LOG_DEVICE_SK")                                   
      20 - filter((SUBSTR("REGISTER_ID_CD",1,1)='4' OR SUBSTR("REGISTER_ID_CD",1,1)='5' OR                                    
                  SUBSTR("REGISTER_ID_CD",1,1)='6') AND "REGISTER_TYPE_CD"='C' AND "ROW_CURRENT_IND"='Y')                                   
      21 - filter("ROW_CURRENT_IND"='Y')                                   
      23 - access("SAP_INT_LOGICAL_REGISTER_SK"="SAP_INT_LOGICAL_REGISTER_SK")                                   
      24 - filter((SUBSTR("REGISTER_ID_CD",1,1)='1' OR SUBSTR("REGISTER_ID_CD",1,1)='2' OR                                    
                  SUBSTR("REGISTER_ID_CD",1,1)='3') AND "REGISTER_TYPE_CD"='C' AND "ROW_CURRENT_IND"='Y')                                   
      25 - filter("ROW_CURRENT_IND"='Y')Edited by: abhilash173 on Feb 24, 2013 9:16 PM
    Edited by: abhilash173 on Feb 24, 2013 9:18 PM

    Hi Paul,
    I misread your question initially .The system stats are outdated in both ( same result as seen from aux_stats) .I am not a DBA and do not have access to gather system stats fresh.
    select * from sys.aux_stats$
    SNAME     PNAME     PVAL1     PVAL2
    SYSSTATS_INFO     STATUS     NULL     COMPLETED
    SYSSTATS_INFO     DSTART     NULL     02-16-2011 15:24
    SYSSTATS_INFO     DSTOP     NULL     02-16-2011 15:24
    SYSSTATS_INFO     FLAGS     1     NULL
    SYSSTATS_MAIN     CPUSPEEDNW     1321.20523     NULL
    SYSSTATS_MAIN     IOSEEKTIM     10     NULL
    SYSSTATS_MAIN     IOTFRSPEED     4096     NULL
    SYSSTATS_MAIN     SREADTIM     NULL     NULL
    SYSSTATS_MAIN     MREADTIM     NULL     NULL
    SYSSTATS_MAIN     CPUSPEED     NULL     NULL
    SYSSTATS_MAIN     MBRC     NULL     NULL
    SYSSTATS_MAIN     MAXTHR     NULL     NULL
    SYSSTATS_MAIN     SLAVETHR     NULL     NULL

  • [oracle 10.2.0.4] My view is not merged

    Hi,
    I have a view which is not merged by the CBO. I mean the CBO decides to apply the filter predicate after the execution of the view.
    Here is the definition of the view
    CREATE OR REPLACE VIEW VUNSCP AS
    SELECT X.DASFM,X.COINT,X.NUCPT,X.RGCOD,X.RGCID,X.CODEV,X.CTDEV,X.CDVRF,X.TXCHJ,X.MTNLV,X.MTVDP,
           LEAD(X.MTNLV+X.MTVDP,1) OVER (PARTITION BY X.COINT,X.NUCPT,X.CDVRF,X.CTDEV,X.CODEV,X.RGCOD,X.RGCID  ORDER BY X.DASFM DESC),
           SUM(X.MTNLV) OVER (PARTITION BY X.COINT,X.CODEV,X.RGCOD)
    FROM SFMCPT XThe query is:
    explain plan for
    select * from VUNSCP where dasfm='30-apr-10';
    select * from table(dbms_xplan.display);
    Plan hash value: 2545326530
    | Id  | Operation           | Name   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT    |        |    13M|  1529M|       |   195K  (1)| 00:39:11 |
    |*  1 |  VIEW               | VUNSCP |    13M|  1529M|       |   195K  (1)| 00:39:11 |
    |   2 |   WINDOW SORT       |        |    13M|   646M|  1996M|   195K  (1)| 00:39:11 |
    |   3 |    TABLE ACCESS FULL| SFMCPT |    13M|   646M|       | 27991   (4)| 00:05:36 |
    Predicate Information (identified by operation id):
       1 - filter("DASFM"='30-apr-10')You can see that a FTS is performed on SFMCPT (>1 million of rows) and that the filter predicate is applied only after the view has been instantiated.
    So the index on DASFM can't be used.
    This query is returning about 30 000 rows. We see on the plan that the CBO is mistaken beacause it reckons that there's going to be 13M of rows.
    If I add the filter predicate directly on the view'script I get the correct plan:
    explain plan for
    SELECT X.DASFM,X.COINT,X.NUCPT,X.RGCOD,X.RGCID,X.CODEV,X.CTDEV,X.CDVRF,X.TXCHJ,X.MTNLV,X.MTVDP,
           LEAD(X.MTNLV+X.MTVDP,1) OVER (PARTITION BY X.COINT,X.NUCPT,X.CDVRF,X.CTDEV,X.CODEV,X.RGCOD,X.RGCID ORDER BY X.DASFM DESC),
           SUM(X.MTNLV) OVER (PARTITION BY X.COINT,X.CODEV,X.RGCOD)
    FROM SFMCPT X where dasfm='30-apr-10';
    select * from table(dbms_xplan.display);
    Plan hash value: 1865390099
    | Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT             |         | 14357 |   729K| 13271   (1)| 00:02:40 |
    |   1 |  WINDOW SORT                 |         | 14357 |   729K| 13271   (1)| 00:02:40 |
    |   2 |   TABLE ACCESS BY INDEX ROWID| SFMCPT  | 14357 |   729K| 13269   (1)| 00:02:40 |
    |*  3 |    INDEX RANGE SCAN          | SFMCPT1 | 14357 |       |    67   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       3 - access("DASFM"='30-apr-10')The index is now used and the rows estimated seem closer to the actual rows.
    I tried several things:
    - disabling the "OPTIMZER_COST_BASED_TRANSFORMATION" hidden parameter
    - use the MERGE hint
    - alter session set optimizer_features_enable = '9.2.0.8';
    All these workarounds don't work => I'm still getting the bad execution plan.
    According to Jonathan LEWIS' s book the 9i optimzer always merge views But here even if I set the optimizer_features_enable parameter to 9i the view is not merged.
    It's sure that the issue is due to the analytical functions but why ?
    Can please someone help me to understand what is going on ?
    Edited by: Ahmed AANGOUR on 5 mai 2010 08:41

    here is the 10053 trace file:
    /oracle/app/oracle/admin/UBIXPROD/udump/ubixprod_ora_24971_10053_optimizer_trace.trc
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
    With the Partitioning, OLAP, Data Mining and Real Application Testing options
    ORACLE_HOME = /oracle/app/oracle/10.2.0
    System name:    Linux
    Node name:      lin-ubi-test1.ubitrade.com
    Release:        2.6.9-78.0.1.ELsmp
    Version:        #1 SMP Tue Jul 22 18:01:05 EDT 2008
    Machine:        x86_64
    Instance name: UBIXPROD
    Redo thread mounted by this instance: 1
    Oracle process number: 26
    *** 2010-05-04 12:14:51.450
    *** ACTION NAME:() 2010-05-04 12:14:51.450
    *** MODULE NAME:([email protected] (TNS V1-V3)) 2010-05-04 12:14:51.450
    *** SERVICE NAME:(SYS$USERS) 2010-05-04 12:14:51.450
    *** SESSION ID:(135.1512) 2010-05-04 12:14:51.450
    Registered qb: SEL$1 0xa9e139a8 (PARSER)
      signature (): qb_name=SEL$1 nbfros=1 flg=0
        fro(0): flg=5 objn=297481 hint_alias="VUNSCP"@"SEL$1"
    Registered qb: SEL$2 0xa9e0bdd0 (PARSER)
      signature (): qb_name=SEL$2 nbfros=1 flg=0
        fro(0): flg=4 objn=265023 hint_alias="X"@"SEL$2"
    Predicate Move-Around (PM)
    PM: Considering predicate move-around in SEL$1 (#0).
    PM:   Checking validity of predicate move-around in SEL$1 (#0).
    CBQT: Validity checks failed for 3xakq94fcx4td.
    CVM: Considering view merge in query block SEL$1 (#0)
    CVM:   Checking validity of merging SEL$2 (#0)
    CVM: Considering view merge in query block SEL$2 (#0)
    CVM:     CVM bypassed: Window functions in this view
    CBQT: Validity checks failed for 3xakq94fcx4td.
    Subquery Unnest
    SU: Considering subquery unnesting in query block SEL$1 (#0)
    Set-Join Conversion (SJC)
    SJC: Considering set-join conversion in SEL$1 (#0).
    Set-Join Conversion (SJC)
    SJC: Considering set-join conversion in SEL$2 (#0).
    Predicate Move-Around (PM)
    PM: Considering predicate move-around in SEL$1 (#0).
    PM:   Checking validity of predicate move-around in SEL$1 (#0).
    PM:   Passed validity checks.
    FPD: Considering simple filter push in SEL$1 (#0)
    FPD:   Current where clause predicates in SEL$1 (#0) :
             "VUNSCP"."DASFM"='30-apr-10'
    kkogcp: try to generate transitive predicate from check constraints for SEL$1 (#0)
    predicates with check contraints: "VUNSCP"."DASFM"='30-apr-10'
    after transitive predicate generation: "VUNSCP"."DASFM"='30-apr-10'
    finally: "VUNSCP"."DASFM"='30-apr-10'
    JPPD:     JPPD bypassed: View not on right-side of outer join
    FPD: Considering simple filter push in SEL$2 (#0)
    FPD:   Current where clause predicates in SEL$2 (#0) :
             apadrv-start: call(in-use=2936, alloc=16344), compile(in-use=38784, alloc=44568)
    kkoqbc-start
                : call(in-use=2936, alloc=16344), compile(in-use=40472, alloc=44568)
    kkoqbc-subheap (create addr=0x2a9740c1f0)
    Current SQL statement for this session:
    EXPLAIN PLAN FOR select * from VUNSCP where dasfm='30-apr-10'
    Peeked values of the binds in SQL statement
    PARAMETERS USED BY THE OPTIMIZER
      PARAMETERS WITH ALTERED VALUES
      _pga_max_size                       = 262140 KB
      cursor_sharing                      = similar
      _optimizer_cost_based_transformation = off
    Column Usage Monitoring is ON: tracking level = 1
    QUERY BLOCK TEXT
    EXPLAIN PLAN FOR select * from VUNSCP where dasfm='30-apr-10'
    QUERY BLOCK SIGNATURE
    qb name was generated
    signature (optimizer): qb_name=SEL$2 nbfros=1 flg=0
      fro(0): flg=0 objn=265023 hint_alias="X"@"SEL$2"
    SYSTEM STATISTICS INFORMATION
      Using NOWORKLOAD Stats
      CPUSPEED: 2503 millions instruction/sec
      IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
      IOSEEKTIM: 10 milliseconds (default is 10)
    BASE STATISTICAL INFORMATION
    Table Stats::
      Table: SFMCPT  Alias:  X
        #Rows: 13036040  #Blks:  122880  AvgRowLen:  358.00
    Index Stats::
      Index: SFMCPT1  Col#: 2 3 4 8 5 7 118
        LVLS: 2  #LB: 58758  #DK: 13013072  LB/K: 1.00  DB/K: 1.00  CLUF: 11983641.00
      Index: SFMCPT2  Col#: 1
        LVLS: 2  #LB: 30031  #DK: 13483987  LB/K: 1.00  DB/K: 1.00  CLUF: 2410599.00
      Index: SFMCPT3  Col#: 3 4 8 5 7 2 118
        LVLS: 2  #LB: 39065  #DK: 13013072  LB/K: 1.00  DB/K: 1.00  CLUF: 12583891.00
    SINGLE TABLE ACCESS PATH
      BEGIN Single Table Cardinality Estimation
      Table: SFMCPT  Alias: X
        Card: Original: 13036040  Rounded: 13036040  Computed: 13036040.00  Non Adjusted: 13036040.00
      END   Single Table Cardinality Estimation
      Access Path: TableScan
        Cost:  27991.05  Resp: 27991.05  Degree: 0
          Cost_io: 26881.00  Cost_cpu: 33334822147
          Resp_io: 26881.00  Resp_cpu: 33334822147
      Best:: AccessPath: TableScan
             Cost: 27991.05  Degree: 1  Resp: 27991.05  Card: 13036040.00  Bytes: 0
    OPTIMIZER STATISTICS AND COMPUTATIONS
    GENERAL PLANS
    Considering cardinality-based initial join order.
    Permutations for Starting Table :0
    Join order[1]:  SFMCPT[X]#0
    WiF sort
        SORT resource      Sort statistics
          Sort width:         766 Area size:     1048576 Max Area size:   134215680
          Degree:               1
          Blocks to Sort:  108528 Row size:           68 Total Rows:       13036040
          Initial runs:         7 Merge passes:        1 IO Cost / pass:      58786
          Total IO sort cost: 167314      Total CPU sort cost: 16584848017
          Total Temp space used: 2093966000
    Best so far: Table#: 0  cost: 195857.3183  card: 13036040.0000  bytes: 677874080
    (newjo-stop-1) k:0, spcnt:0, perm:1, maxperm:80000
    Number of join permutations tried: 1
        SORT resource      Sort statistics
          Sort width:         766 Area size:     1048576 Max Area size:   134215680
          Degree:               1
          Blocks to Sort:  108528 Row size:           68 Total Rows:       13036040
          Initial runs:         7 Merge passes:        1 IO Cost / pass:      58786
          Total IO sort cost: 167314      Total CPU sort cost: 16584848017
          Total Temp space used: 2093966000
    Final - All Rows Plan:  Best join order: 1
      Cost: 195857.3183  Degree: 1  Card: 13036040.0000  Bytes: 677874080
      Resc: 195857.3183  Resc_io: 194195.0000  Resc_cpu: 49919670164
      Resp: 195857.3183  Resp_io: 194195.0000  Resc_cpu: 49919670164
    kkoipt: Query block SEL$2 (#0)
    ******* UNPARSED QUERY IS *******
    SELECT "X"."DASFM" "DASFM","X"."COINT" "COINT","X"."NUCPT" "NUCPT","X"."RGCOD" "RGCOD","X"."RGCID" "RGCID","X"."CODEV" "CODEV","X"."CTDEV" "CTDEV","X"."CDVRF" "CDVRF","X"."TXCHJ" "TXCHJ","X"."MTNLV" "MTNLV","X"."MTVDP" "MTVDP",DECODE(COUNT(*) OVER ( PARTITION BY "X"."COINT","X"."CODEV","X"."RGCOD","X"."CTDEV","X"."NUCPT","X"."CDVRF","X"."RGCID" ORDER BY "X"."DASFM" DESC  ROWS  BETWEEN 1 FOLLOWING  AND 1 FOLLOWING ),1,FIRST_VALUE("X"."MTNLV"+"X"."MTVDP") OVER ( PARTITION BY "X"."COINT","X"."CODEV","X"."RGCOD","X"."CTDEV","X"."NUCPT","X"."CDVRF","X"."RGCID" ORDER BY "X"."DASFM" DESC  ROWS  BETWEEN 1 FOLLOWING  AND 1 FOLLOWING ),NULL) "MTUNS",SUM("X"."MTNLV") OVER ( PARTITION BY "X"."COINT","X"."CODEV","X"."RGCOD") "MTNLI" FROM "SFMCPT" "X"
    kkoqbc-subheap (delete addr=0x2a9740c1f0, in-use=11856, alloc=12408)
    kkoqbc-end
              : call(in-use=57760, alloc=81816), compile(in-use=41096, alloc=44568)
    kkoqbc-start
                : call(in-use=57760, alloc=81816), compile(in-use=41184, alloc=44568)
    kkoqbc-subheap (create addr=0x2a9746b058)
    QUERY BLOCK TEXT
    select * from VUNSCP where dasfm='30-apr-10'
    QUERY BLOCK SIGNATURE
    qb name was generated
    signature (optimizer): qb_name=SEL$1 nbfros=1 flg=0
      fro(0): flg=1 objn=297481 hint_alias="VUNSCP"@"SEL$1"
    SYSTEM STATISTICS INFORMATION
      Using NOWORKLOAD Stats
      CPUSPEED: 2503 millions instruction/sec
      IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
      IOSEEKTIM: 10 milliseconds (default is 10)
    BASE STATISTICAL INFORMATION
    Table Stats::
      Table: VUNSCP  Alias: VUNSCP  (NOT ANALYZED)
        #Rows: 0  #Blks:  0  AvgRowLen:  0.00
    OPTIMIZER STATISTICS AND COMPUTATIONS
    GENERAL PLANS
    Considering cardinality-based initial join order.
    Permutations for Starting Table :
    Join order[1]:  VUNSCP[VUNSCP]#0
    Best so far: Table#: 0  cost: 195857.3183  card: 13036040.0000  bytes: 1603432920
    (newjo-stop-1) k:0, spcnt:0, perm:1, maxperm:80000
    Number of join permutations tried: 1
    Final - All Rows Plan:  Best join order: 1
      Cost: 195857.3183  Degree: 1  Card: 13036040.0000  Bytes: 1603432920
      Resc: 195857.3183  Resc_io: 194195.0000  Resc_cpu: 49919670164
      Resp: 195857.3183  Resp_io: 194195.0000  Resc_cpu: 49919670164
    kkoipt: Query block SEL$1 (#0)
    ******* UNPARSED QUERY IS *******
    SELECT "VUNSCP"."DASFM" "DASFM","VUNSCP"."COINT" "COINT","VUNSCP"."NUCPT" "NUCPT","VUNSCP"."RGCOD" "RGCOD","VUNSCP"."RGCID" "RGCID","VUNSCP"."CODEV" "CODEV","VUNSCP"."CTDEV" "CTDEV","VUNSCP"."CDVRF" "CDVRF","VUNSCP"."TXCHJ" "TXCHJ","VUNSCP"."MTNLV" "MTNLV","VUNSCP"."MTVDP" "MTVDP","VUNSCP"."MTUNS" "MTUNS","VUNSCP"."MTNLI" "MTNLI" FROM  (SELECT "X"."DASFM" "DASFM","X"."COINT" "COINT","X"."NUCPT" "NUCPT","X"."RGCOD" "RGCOD","X"."RGCID" "RGCID","X"."CODEV" "CODEV","X"."CTDEV" "CTDEV","X"."CDVRF" "CDVRF","X"."TXCHJ" "TXCHJ","X"."MTNLV" "MTNLV","X"."MTVDP" "MTVDP",DECODE(COUNT(*) OVER ( PARTITION BY "X"."COINT","X"."CODEV","X"."RGCOD","X"."CTDEV","X"."NUCPT","X"."CDVRF","X"."RGCID" ORDER BY "X"."DASFM" DESC  ROWS  BETWEEN 1 FOLLOWING  AND 1 FOLLOWING ),1,FIRST_VALUE("X"."MTNLV"+"X"."MTVDP") OVER ( PARTITION BY "X"."COINT","X"."CODEV","X"."RGCOD","X"."CTDEV","X"."NUCPT","X"."CDVRF","X"."RGCID" ORDER BY "X"."DASFM" DESC  ROWS  BETWEEN 1 FOLLOWING  AND 1 FOLLOWING ),NULL) "MTUNS",SUM("X"."MTNLV") OVER ( PARTITION BY "X"."COINT","X"."CODEV","X"."RGCOD") "MTNLI" FROM "SFMCPT" "X") "VUNSCP" WHERE "VUNSCP"."DASFM"='30-apr-10'
    kkoqbc-subheap (delete addr=0x2a9746b058, in-use=11544, alloc=12408)
    kkoqbc-end
              : call(in-use=63208, alloc=81816), compile(in-use=41688, alloc=44568)
    apadrv-end: call(in-use=63208, alloc=81816), compile(in-use=42872, alloc=44568)
    sql_id=3xakq94fcx4td.
    Current SQL statement for this session:
    EXPLAIN PLAN FOR select * from VUNSCP where dasfm='30-apr-10'
    ============
    Plan Table
    ============
    ---------------------------------------+-----------------------------------+
    | Id  | Operation            | Name    | Rows  | Bytes | Cost  | Time      |
    ---------------------------------------+-----------------------------------+
    | 0   | SELECT STATEMENT     |         |       |       |  191K |           |
    | 1   |  VIEW                | VUNSCP  |   12M | 1529M |  191K |  00:39:11 |
    | 2   |   WINDOW SORT        |         |   12M |  646M |  191K |  00:39:11 |
    | 3   |    TABLE ACCESS FULL | SFMCPT  |   12M |  646M |   27K |  00:06:36 |
    ---------------------------------------+-----------------------------------+
    Predicate Information:
    1 - filter("DASFM"='30-apr-10')Edited by: Ahmed AANGOUR on 5 mai 2010 08:43

  • CBO bug? Lack of SORT UNIQUE.

    Hi all,
    Let's consider following case:
    create table tmp as select rownum id, 0 sign from dual connect by level <= 100;
    create index tmp_i on tmp(id,sign);
    create table t as
    select mod(rownum,2) id, mod(rownum,3) val
    from dual
    connect by level <= 100000;
    begin
       dbms_stats.gather_table_stats (
          user,
          'T',
          estimate_percent   => null,
          method_opt         => 'FOR ALL COLUMNS SIZE SKEWONLY',
          cascade            => true
    end;
    begin
       dbms_stats.gather_table_stats (
          user,
          'TMP',
          estimate_percent   => null,
          method_opt         => 'FOR ALL COLUMNS SIZE SKEWONLY',
          cascade            => true
    end;
    /As you can see it scans TMP_I 50 000 times for statement with max (irrespective of distinct in subquery).
    Is there any way to enforce CBO to make SORT UNIQUE for max as well as for count so that it scans TMP_I only 3 times?
    SQL> select --+ leading(t) use_nl(t tmp)
      2  max(id)
      3  from tmp tmp
      4  where tmp.sign = 0
      5  and tmp.id in (select val from t where id = 1);
       MAX(ID)
             2
    | Id  | Operation           | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    |   0 | SELECT STATEMENT    |       |      1 |        |      1 |00:00:00.14 |     159 |
    |   1 |  SORT AGGREGATE     |       |      1 |      1 |      1 |00:00:00.14 |     159 |
    |   2 |   NESTED LOOPS      |       |      1 |  49750 |  33333 |00:00:00.13 |     159 |
    |*  3 |    TABLE ACCESS FULL| T     |      1 |  50000 |  50000 |00:00:00.02 |     156 |
    |*  4 |    INDEX RANGE SCAN | TMP_I |  50000 |      1 |  33333 |00:00:00.07 |       3 |
    Predicate Information (identified by operation id):
       3 - filter("ID"=1)
       4 - access("TMP"."ID"="VAL" AND "TMP"."SIGN"=0)
    SQL> select --+ leading(t) use_nl(t tmp)
      2  max(id)
      3  from tmp tmp
      4  where tmp.sign = 0
      5  and tmp.id in (select distinct val from t where id = 1);
       MAX(ID)
             2
    | Id  | Operation           | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    |   0 | SELECT STATEMENT    |       |      1 |        |      1 |00:00:00.14 |     159 |
    |   1 |  SORT AGGREGATE     |       |      1 |      1 |      1 |00:00:00.14 |     159 |
    |   2 |   NESTED LOOPS      |       |      1 |  49750 |  33333 |00:00:00.13 |     159 |
    |*  3 |    TABLE ACCESS FULL| T     |      1 |  50000 |  50000 |00:00:00.01 |     156 |
    |*  4 |    INDEX RANGE SCAN | TMP_I |  50000 |      1 |  33333 |00:00:00.07 |       3 |
    Predicate Information (identified by operation id):
       3 - filter("ID"=1)
       4 - access("TMP"."ID"="VAL" AND "TMP"."SIGN"=0)
    SQL> select --+ leading(t) use_nl(t tmp)
      2  count(id)
      3  from tmp tmp
      4  where tmp.sign = 0
      5  and tmp.id in (select val from t where id = 1);
    COUNT(ID)
             2
    | Id  | Operation            | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    |   0 | SELECT STATEMENT     |       |      1 |        |      1 |00:00:00.03 |     158 |       |       |          |
    |   1 |  SORT AGGREGATE      |       |      1 |      1 |      1 |00:00:00.03 |     158 |       |       |          |
    |   2 |   NESTED LOOPS       |       |      1 |      3 |      2 |00:00:00.03 |     158 |       |       |          |
    |   3 |    SORT UNIQUE       |       |      1 |  50000 |      3 |00:00:00.03 |     156 |  2048 |  2048 | 2048  (0)|
    |*  4 |     TABLE ACCESS FULL| T     |      1 |  50000 |  50000 |00:00:00.01 |     156 |       |       |          |
    |*  5 |    INDEX RANGE SCAN  | TMP_I |      3 |      1 |      2 |00:00:00.01 |       2 |       |       |          |
    Predicate Information (identified by operation id):
       4 - filter("ID"=1)
       5 - access("TMP"."ID"="VAL" AND "TMP"."SIGN"=0)I can't figure out why SORT UNIQUE is absent for statement with max.
    PS. 11gR2

    Thanks for reply.
    user503699 wrote:
    I don't think it is a good idea to compare your last and first query timings as they are 2 different queries.Ok. I could compare query with max(id), sign(count(*)+1) vs max(id), sign(1). They always produce the same results so can be considered as the same.
    But I think that max(id), count(*) vs max(id) was enough to explain my point.
    user503699 wrote:
    If you are so sure of that you can write something like following :
    SQL> with data as (select /*+ materialize */ distinct val as val from t where id = 1)
    select max(id) from tmp tmp where tmp.sign = 0 and tmp.id in (select val from data) ;  2 
    I thought about that. I’m reluctant to use undocumented hints such as materialize. So folowing query has almost the best plan for my data:
    with data as (select distinct val as val from t where id = 1 and rownum > 0)
    select
    max(id)
    from tmp tmp
    where tmp.sign = 0
    and tmp.id in (select * from data);
    | Id  | Operation               | Name  | Rows  | Bytes | Cost (%CPU)| Time     |                                                                    
    |   0 | SELECT STATEMENT        |       |     1 |     8 |    50   (8)| 00:00:01 |                                                                    
    |   1 |  SORT AGGREGATE         |       |     1 |     8 |            |          |                                                                    
    |   2 |   NESTED LOOPS          |       |     3 |    24 |    50   (8)| 00:00:01 |                                                                    
    |   3 |    VIEW                 |       |     3 |     9 |    50   (8)| 00:00:01 |                                                                    
    |   4 |     HASH UNIQUE         |       |     3 |    18 |    50   (8)| 00:00:01 |                                                                    
    |   5 |      COUNT              |       |       |       |            |          |                                                                    
    |*  6 |       FILTER            |       |       |       |            |          |                                                                    
    |*  7 |        TABLE ACCESS FULL| T     | 50000 |   292K|    47   (3)| 00:00:01 |                                                                    
    |*  8 |    INDEX RANGE SCAN     | TMP_I |     1 |     5 |     0   (0)| 00:00:01 |                                                                    
    Predicate Information (identified by operation id):                                                                                                  
       6 - filter(ROWNUM>0)                                                                                                                              
       7 - filter("ID"=1)                                                                                                                                
       8 - access("TMP"."ID"="DATA"."VAL" AND "TMP"."SIGN"=0)   And changing two hidden parameters may lead to the same plan as I expect:
    alter session set "_gby_hash_aggregation_enabled" = false;
    alter session set "_simple_view_merging" = false;
    with data as (select distinct val as val from t where id = 1)
    select
    max(id)
    from tmp tmp
    where tmp.sign = 0
    and tmp.id in (select * from data);
    | Id  | Operation             | Name  | Rows  | Bytes | Cost (%CPU)| Time     |                                                                      
    |   0 | SELECT STATEMENT      |       |     1 |    18 |    50   (8)| 00:00:01 |                                                                      
    |   1 |  SORT AGGREGATE       |       |     1 |    18 |            |          |                                                                      
    |   2 |   NESTED LOOPS        |       |     3 |    54 |    50   (8)| 00:00:01 |                                                                      
    |   3 |    VIEW               |       |     3 |    39 |    50   (8)| 00:00:01 |                                                                      
    |   4 |     SORT UNIQUE       |       |     3 |    18 |    50   (8)| 00:00:01 |                                                                      
    |*  5 |      TABLE ACCESS FULL| T     | 50000 |   292K|    47   (3)| 00:00:01 |                                                                      
    |*  6 |    INDEX RANGE SCAN   | TMP_I |     1 |     5 |     0   (0)| 00:00:01 |                                                                      
    Predicate Information (identified by operation id):                                                                                                  
       5 - filter("ID"=1)                                                                                                                                
       6 - access("TMP"."ID"="DATA"."VAL" AND "TMP"."SIGN"=0)   But here I've got two additional questions:
    1. no_use_hash_aggregation can be used instead of "alter session set "_gby_hash_aggregation_enabled" = false;"
    What hint can be used instead of "alter session set "_simple_view_merging" = false;"?
    2. Is there any way to enforce CBO to use for this one
    select
    max(id)
    from tmp tmp
    where tmp.sign = 0
    and tmp.id in (select distinct val as val from t where id = 1 and rownum > 0);
    | Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |                                                                
    |   0 | SELECT STATEMENT            |       |     1 |     5 |     3   (0)| 00:00:01 |                                                                
    |   1 |  SORT AGGREGATE             |       |     1 |     5 |            |          |                                                                
    |   2 |   FIRST ROW                 |       |     1 |     5 |     1   (0)| 00:00:01 |                                                                
    |*  3 |    INDEX FULL SCAN (MIN/MAX)| TMP_I |     1 |     5 |     1   (0)| 00:00:01 |                                                                
    |*  4 |     FILTER                  |       |       |       |            |          |                                                                
    |   5 |      COUNT                  |       |       |       |            |          |                                                                
    |*  6 |       FILTER                |       |       |       |            |          |                                                                
    |*  7 |        TABLE ACCESS FULL    | T     |     2 |    12 |     2   (0)| 00:00:01 |                                                                
    -------------------------------------------------------------------------------------  the same plan as for this
    with data as (select distinct val as val from t where id = 1 and rownum > 0)
    select
    max(id)
    from tmp tmp
    where tmp.sign = 0
    and tmp.id in (select * from data);
    | Id  | Operation               | Name  | Rows  | Bytes | Cost (%CPU)| Time     |                                                                    
    |   0 | SELECT STATEMENT        |       |     1 |     8 |    50   (8)| 00:00:01 |                                                                    
    |   1 |  SORT AGGREGATE         |       |     1 |     8 |            |          |                                                                    
    |   2 |   NESTED LOOPS          |       |     3 |    24 |    50   (8)| 00:00:01 |                                                                    
    |   3 |    VIEW                 |       |     3 |     9 |    50   (8)| 00:00:01 |                                                                    
    |   4 |     HASH UNIQUE         |       |     3 |    18 |    50   (8)| 00:00:01 |                                                                    
    |   5 |      COUNT              |       |       |       |            |          |                                                                    
    |*  6 |       FILTER            |       |       |       |            |          |                                                                    
    |*  7 |        TABLE ACCESS FULL| T     | 50000 |   292K|    47   (3)| 00:00:01 |                                                                    
    |*  8 |    INDEX RANGE SCAN     | TMP_I |     1 |     5 |     0   (0)| 00:00:01 |                                                                    
    I don't have anything against subquery factoring clause. Just for personal interest.
    (I have read topic "Thread: Materialize a Subquery without using "with" clause"
    Materialize a Subquery without using "with" clause
    user503699 wrote:
    If you are not going to change other things (like stats collection method, table/index structures etc.) which allow optimizer to choose better plan and you know your data better, you may need to be very specific with the hints and also may have to use additional hints in order to influence optimizer decisions.
    One way to do that would be to get the base details from oracle as follows (and tweak them) :I didn't find keyword "ADVANCED" in specification for DISPLAY_CURSOR Function in documentation. Nice trick.
    But anyway outline data makes sense only in case when query already has desirable execution plan.

  • Subquery conditional execution using cbo

    hellou
    how i do for execute a subquery conditionally, using the cbo??
    i got an example:
    create table table1 AS
    SELECT * FROM (
        SELECT 1 id, 'a' boss FROM dual
       union all
        SELECT 3 id, 'b' boss FROM dual
       union all
        SELECT 5 id, 'a' boss FROM dual
       union all
        SELECT 7 id, 'b' boss FROM dual
       union all
        SELECT 9 id, 'a' boss FROM dual
    create index idx_table1 on table1(boss, id)
    create table table2 AS
    SELECT * FROM (
        SELECT 2 id, 'b' boss FROM dual
       union all
        SELECT 4 id, 'a' boss FROM dual
       union all
        SELECT 6 id, 'b' boss FROM dual
       union all
        SELECT 8 id, 'a' boss FROM dual
       union all
        SELECT 10 id, 'b' boss FROM dual
    create index idx_table2 on table2(boss, id)
    CREATE OR REPLACE FUNCTION print_hi
        isb in varchar2
    return number
    IS
    BEGIN
        dbms_output.put_Line(isb);
        return 0;
    END;
    -- the query !!!!!!!
    with data AS
        SELECT
        FROM (
            -- subquery #1
            SELECT
                1 query_name,
                id pibot,
                boss
            FROM table1
            WHERE print_hi(id) = 0
           union all
            -- subquery #2
            SELECT
                2 query_name,
                id pibot,
                boss
            FROM table2
    SELECT
        pibot + query_name / 10 pibot
    FROM data
    WHERE 1 = 1
        AND boss = :boss
        AND (
            query_name = :q
            AND pibot > :p
           OR query_name > :q )
        AND rownum <= 3i want than only the query #2 be executed.
    the query #1 print data in the screen when is executed (for the function print_hi).
    now i execute the query with the variables data as:
    boss = 'a'
    q = 2
    p = 0
    when i execute the query using rules, then not print anything in the screen.
    when i execute the query using costs, then print 1 5 9 in the screen. this means than the query #1 is being executed when this should not
    help .. tx
    SELECT * FROM v$version
    Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - Prod
    PL/SQL Release 10.2.0.5.0 - Production
    CORE10.2.0.5.0Production
    TNS for Linux: Version 10.2.0.5.0 - Production
    NLSRTL Version 10.2.0.5.0 - Production

    As often is, the predicates section of the execution plan is quite revealing on this one.
    Take your original query
    explain plan for
    with data AS
    (SELECT *
    FROM (-- subquery #1
           SELECT 1 query_name,id pibot,boss
           FROM table1
           WHERE print_hi(id) = 0
           union all
            -- subquery #2
           SELECT 2 query_name,id pibot,boss
            FROM table2))
    SELECT pibot + query_name / 10 pibot
    FROM   data
    WHERE  1 = 1
    AND    boss = :boss
    AND   (query_name = :q
    AND    pibot > :p
    OR     query_name > :q )
    AND    rownum <= 3;
    select * from table(dbms_xplan.display);gives
    | Id  | Operation           | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT    |            |     2 |    38 |     2   (0)| 00:00:01 |
    |*  1 |  COUNT STOPKEY      |            |       |       |            |          |
    |   2 |   VIEW              |            |     2 |    38 |     2   (0)| 00:00:01 |
    |   3 |    UNION-ALL        |            |       |       |            |          |
    |*  4 |     INDEX RANGE SCAN| IDX_TABLE1 |     1 |    16 |     1   (0)| 00:00:01 |
    |*  5 |     INDEX RANGE SCAN| IDX_TABLE2 |     1 |    16 |     1   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - filter(ROWNUM<=3)
       4 - access("BOSS"=:BOSS)
           filter("PRINT_HI"(TO_CHAR("ID"))=0 AND (1>TO_NUMBER(:Q) OR
                  1=TO_NUMBER(:Q) AND "ID">TO_NUMBER(:P)))
       5 - access("BOSS"=:BOSS)
           filter(2>TO_NUMBER(:Q) OR 2=TO_NUMBER(:Q) AND "ID">TO_NUMBER(:P))Assuming that the FILTER logic in STEP 4 is followed to order, it's not then possible with this query as is to short-circuit the evaluation of PRINT_HI as it is evaluated first.
    When you make a change (just to q not necessarily to boss as well)
    from
    query_name = :qto
    query_name = 2You'll hopefully notice the difference in predicate evaluation with the extra filter step:
    | Id  | Operation             | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT      |            |     2 |    38 |     2   (0)| 00:00:01 |
    |*  1 |  COUNT STOPKEY        |            |       |       |            |          |
    |   2 |   VIEW                |            |     2 |    38 |     2   (0)| 00:00:01 |
    |   3 |    VIEW               |            |     2 |    38 |     2   (0)| 00:00:01 |
    |   4 |     UNION-ALL         |            |       |       |            |          |
    |*  5 |      FILTER           |            |       |       |            |          |
    |*  6 |       INDEX RANGE SCAN| IDX_TABLE1 |     1 |    16 |     1   (0)| 00:00:01 |
    |*  7 |      INDEX RANGE SCAN | IDX_TABLE2 |     1 |    16 |     1   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - filter(ROWNUM<=3)
       5 - filter(1>TO_NUMBER(:Q))
       6 - access("BOSS"=:BOSS)
           filter("PRINT_HI"(TO_CHAR("ID"))=0)
       7 - access("BOSS"=:BOSS)
           filter("ID">TO_NUMBER(:P) OR 2>TO_NUMBER(:Q))

  • Query rewrite by CBO

    Hello,
    Some days back, I came across a blog entry in which author concluded that when a = b and b = c, oracle does not conclude as a = c. He also provided a test case to prove his point. The URL is [http://sandeepredkar.blogspot.com/2009/09/query-performance-join-conditions.html]
    Now, I thought that that can not be true. So I executed his test case (on 10.2.04) and the outcome indeed proved his point. Initially, I thought it might be due to absense of PK-FK relationship. But even after adding the PK-FK relationship, there was no change in the outcome. Although, when I modified the subquery with list of values, both the queries performed equally. I tried asking the author on his blog but it seems he has not yet seen my comment.
    I am pasting his test case below. Can somebody please help me understand why CBO does not/can not use optimal plan here?
    SQL> create table cu_all (custid number, addr varchar2(200), ph number, cano number, acctype varchar2(10));
    Table created.
    SQL> create table ca_receipt (custid number, caamt number, cadt date, totbal number);
    Table created.
    SQL>
    SQL> insert into cu_all
      2  select     lvl,
      3          dbms_random.string('A',30),
      4          round(dbms_random.value(1,100000)),
      5          round(dbms_random.value(1,10000)),
      6          dbms_random.string('A',10)
      7  from       (select level "LVL" from dual connect by level <=200000);
    200000 rows created.
    SQL> insert into ca_receipt
      2  select     round(dbms_random.value(1,10000)),
      3          round(dbms_random.value(1,100000)),
      4          sysdate - round(dbms_random.value(1,100000)),
      5          round(dbms_random.value(1,100000))
      6  from       (select level "LVL" from dual connect by level <=500000);
    500000 rows created.
    SQL> create unique index pk_cu_all_ind on cu_all(custid);
    Index created.
    SQL> create index ind2_cu_all on cu_all(CANO);
    Index created.
    SQL> create index ind_ca_receipt_custid on ca_receipt(custid);
    Index created.
    SQL> exec dbms_stats.gather_table_stats(user,'CU_ALL', cascade=>true);
    PL/SQL procedure successfully completed.
    SQL> exec dbms_stats.gather_table_stats(user,'CA_RECEIPT', cascade=>true);
    PL/SQL procedure successfully completed.
    Now let us execute the query with trace on. This is the similar query which was provided to me.
    SQL> set autot trace
    SQL> SELECT     ca.*, cu.*
      2  FROM ca_receipt CA,
      3       cu_all CU
      4  WHERE       CA.CUSTID = CU.CUSTID
      5  AND         CA.CUSTID IN (SELECT CUSTID FROM cu_all START WITH custid = 2353
      6                CONNECT BY PRIOR CUSTID = CANO)
      7  ORDER BY ACCTYPE DESC;
    289 rows selected.
    Execution Plan
    Plan hash value: 3186098611
    | Id  | Operation                           | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                    |                       |  1000 | 81000 |   504   (2)| 00:00:07 |
    |   1 |  SORT ORDER BY                      |                       |  1000 | 81000 |   504   (2)| 00:00:07 |
    |*  2 |   HASH JOIN                         |                       |  1000 | 81000 |   503   (2)| 00:00:07 |
    |   3 |    NESTED LOOPS                     |                       |       |       |            |          |
    |   4 |     NESTED LOOPS                    |                       |  1000 | 26000 |   112   (1)| 00:00:02 |
    |   5 |      VIEW                           | VW_NSO_1              |    20 |   100 |    21   (0)| 00:00:01 |
    |   6 |       HASH UNIQUE                   |                       |    20 |   180 |            |          |
    |*  7 |        CONNECT BY WITH FILTERING    |                       |       |       |            |          |
    |   8 |         TABLE ACCESS BY INDEX ROWID | CU_ALL                |     1 |     9 |     2   (0)| 00:00:01 |
    |*  9 |          INDEX UNIQUE SCAN          | PK_CU_ALL_IND         |     1 |       |     1   (0)| 00:00:01 |
    |  10 |         NESTED LOOPS                |                       |       |       |            |          |
    |  11 |          CONNECT BY PUMP            |                       |       |       |            |          |
    |  12 |          TABLE ACCESS BY INDEX ROWID| CU_ALL                |    20 |   180 |    21   (0)| 00:00:01 |
    |* 13 |           INDEX RANGE SCAN          | IND2_CU_ALL           |    20 |       |     1   (0)| 00:00:01 |
    |* 14 |      INDEX RANGE SCAN               | IND_CA_RECEIPT_CUSTID |    50 |       |     2   (0)| 00:00:01 |
    |  15 |     TABLE ACCESS BY INDEX ROWID     | CA_RECEIPT            |    50 |  1050 |    52   (0)| 00:00:01 |
    |  16 |    TABLE ACCESS FULL                | CU_ALL                |   200K|    10M|   389   (1)| 00:00:05 |
    Predicate Information (identified by operation id):
       2 - access("CA"."CUSTID"="CU"."CUSTID")
       7 - access("CANO"=PRIOR "CUSTID")
       9 - access("CUSTID"=2353)
      13 - access("CANO"=PRIOR "CUSTID")
      14 - access("CA"."CUSTID"="CUSTID")
    Statistics
              1  recursive calls
              0  db block gets
           2249  consistent gets
             25  physical reads
              0  redo size
          11748  bytes sent via SQL*Net to client
            729  bytes received via SQL*Net from client
             21  SQL*Net roundtrips to/from client
              7  sorts (memory)
              0  sorts (disk)
            289  rows processed
    If you look at the query, it seems to be normal one.
    But the problem is here-
    Query is having two tables CA and CU. From the inner CU table query, it fetches records and joins with CA table an CA table Joins with CU table using the same column.
    Here the inner query joins with CA table and cardinality of the query gets changed. So it is opting FTS when joining to CU table again.
    This is causing the performance bottleneck. So to resolve the issue, I have change the joining condition.
    Now if we check, following is the proper execution plan. Also the consistents gets have been reduced to 797 against 2249 in original query.
    SQL> SELECT     ca.*, cu.*
      2  FROM ca_receipt CA,
      3       cu_all CU
      4  WHERE       CA.CUSTID = CU.CUSTID
      5  AND         CU.CUSTID IN (SELECT CUSTID FROM cu_all START WITH custid = 2353
      6                CONNECT BY PRIOR CUSTID = CANO)
      7  ORDER BY ACCTYPE DESC;
    289 rows selected.
    Execution Plan
    Plan hash value: 3713271440
    | Id  | Operation                           | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                    |                       |  1000 | 81000 |   133   (2)| 00:00:02 |
    |   1 |  SORT ORDER BY                      |                       |  1000 | 81000 |   133   (2)| 00:00:02 |
    |   2 |   NESTED LOOPS                      |                       |       |       |            |          |
    |   3 |    NESTED LOOPS                     |                       |  1000 | 81000 |   132   (1)| 00:00:02 |
    |   4 |     NESTED LOOPS                    |                       |    20 |  1200 |    42   (3)| 00:00:01 |
    |   5 |      VIEW                           | VW_NSO_1              |    20 |   100 |    21   (0)| 00:00:01 |
    |   6 |       HASH UNIQUE                   |                       |    20 |   180 |            |          |
    |*  7 |        CONNECT BY WITH FILTERING    |                       |       |       |            |          |
    |   8 |         TABLE ACCESS BY INDEX ROWID | CU_ALL                |     1 |     9 |     2   (0)| 00:00:01 |
    |*  9 |          INDEX UNIQUE SCAN          | PK_CU_ALL_IND         |     1 |       |     1   (0)| 00:00:01 |
    |  10 |         NESTED LOOPS                |                       |       |       |            |          |
    |  11 |          CONNECT BY PUMP            |                       |       |       |            |          |
    |  12 |          TABLE ACCESS BY INDEX ROWID| CU_ALL                |    20 |   180 |    21   (0)| 00:00:01 |
    |* 13 |           INDEX RANGE SCAN          | IND2_CU_ALL           |    20 |       |     1   (0)| 00:00:01 |
    |  14 |      TABLE ACCESS BY INDEX ROWID    | CU_ALL                |     1 |    55 |     1   (0)| 00:00:01 |
    |* 15 |       INDEX UNIQUE SCAN             | PK_CU_ALL_IND         |     1 |       |     0   (0)| 00:00:01 |
    |* 16 |     INDEX RANGE SCAN                | IND_CA_RECEIPT_CUSTID |    50 |       |     2   (0)| 00:00:01 |
    |  17 |    TABLE ACCESS BY INDEX ROWID      | CA_RECEIPT            |    50 |  1050 |    52   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       7 - access("CANO"=PRIOR "CUSTID")
       9 - access("CUSTID"=2353)
      13 - access("CANO"=PRIOR "CUSTID")
      15 - access("CU"."CUSTID"="CUSTID")
      16 - access("CA"."CUSTID"="CU"."CUSTID")
    Statistics
              1  recursive calls
              0  db block gets
            797  consistent gets
              1  physical reads
              0  redo size
          11748  bytes sent via SQL*Net to client
            729  bytes received via SQL*Net from client
             21  SQL*Net roundtrips to/from client
              7  sorts (memory)
              0  sorts (disk)
            289  rows processed

    user503699 wrote:
    Hello,
    Some days back, I came across a blog entry in which author concluded that when a = b and b = c, oracle does not conclude as a = c. He also provided a test case to prove his point. The URL is [http://sandeepredkar.blogspot.com/2009/09/query-performance-join-conditions.html]
    Now, I thought that that can not be true. So I executed his test case (on 10.2.04) and the outcome indeed proved his point. Initially, I thought it might be due to absense of PK-FK relationship. But even after adding the PK-FK relationship, there was no change in the outcome. Although, when I modified the subquery with list of values, both the queries performed equally. I tried asking the author on his blog but it seems he has not yet seen my comment.I see that Jonathan provided a helpful reply to you while I was in the process of setting up a test case.
    Is it possible that the optimizer is correct? What if... the optimizer transformed the SQL statement? What if... the original SQL statement actually executes faster than the modified SQL statement? What if... the autotrace plans do not match the plans shown on that web page?
    The first execution with the original SQL statement:
    ALTER SESSION SET EVENTS '10053 trace name context forever, level 1';
    ALTER SESSION SET TRACEFILE_IDENTIFIER = 'test_case';
    SET AUTOTRACE TRACE
    SELECT     ca.*, cu.*
    FROM ca_receipt CA,
         cu_all CU
    WHERE       CA.CUSTID = CU.CUSTID
    AND         CA.CUSTID IN (SELECT CUSTID FROM cu_all START WITH custid = 2353
                  CONNECT BY PRIOR CUSTID = CANO)
    ORDER BY ACCTYPE DESC;
    Execution Plan
    Plan hash value: 2794552689
    | Id  | Operation                          | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                   |                       |  1001 | 81081 |  1125   (2)| 00:00:01 |
    |   1 |  SORT ORDER BY                     |                       |  1001 | 81081 |  1125   (2)| 00:00:01 |
    |   2 |   NESTED LOOPS                     |                       |  1001 | 81081 |  1123   (1)| 00:00:01 |
    |   3 |    NESTED LOOPS                    |                       |  1001 | 26026 |   114   (2)| 00:00:01 |
    |   4 |     VIEW                           | VW_NSO_1              |    20 |   100 |    22   (0)| 00:00:01 |
    |   5 |      HASH UNIQUE                   |                       |    20 |   180 |            |          |
    |*  6 |       CONNECT BY WITH FILTERING    |                       |       |       |            |          |
    |   7 |        TABLE ACCESS BY INDEX ROWID | CU_ALL                |     1 |    19 |     2   (0)| 00:00:01 |
    |*  8 |         INDEX UNIQUE SCAN          | PK_CU_ALL_IND         |     1 |       |     1   (0)| 00:00:01 |
    |   9 |        NESTED LOOPS                |                       |       |       |            |          |
    |  10 |         CONNECT BY PUMP            |                       |       |       |            |          |
    |  11 |         TABLE ACCESS BY INDEX ROWID| CU_ALL                |    20 |   180 |    22   (0)| 00:00:01 |
    |* 12 |          INDEX RANGE SCAN          | IND2_CU_ALL           |    20 |       |     1   (0)| 00:00:01 |
    |  13 |     TABLE ACCESS BY INDEX ROWID    | CA_RECEIPT            |    50 |  1050 |    52   (0)| 00:00:01 |
    |* 14 |      INDEX RANGE SCAN              | IND_CA_RECEIPT_CUSTID |    50 |       |     2   (0)| 00:00:01 |
    |  15 |    TABLE ACCESS BY INDEX ROWID     | CU_ALL                |     1 |    55 |     1   (0)| 00:00:01 |
    |* 16 |     INDEX UNIQUE SCAN              | PK_CU_ALL_IND         |     1 |       |     0   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       6 - access("CANO"=PRIOR "CUSTID")
       8 - access("CUSTID"=2353)
      12 - access("CANO"=PRIOR "CUSTID")
      14 - access("CA"."CUSTID"="$nso_col_1")
      16 - access("CA"."CUSTID"="CU"."CUSTID")
    Statistics
              1  recursive calls
              0  db block gets
            232  consistent gets
              7  physical reads
              0  redo size
           2302  bytes sent via SQL*Net to client
            379  bytes received via SQL*Net from client
              5  SQL*Net roundtrips to/from client
              5  sorts (memory)
              0  sorts (disk)
             52  rows processedThe second SQL statement which was modified:
    ALTER SESSION SET TRACEFILE_IDENTIFIER = 'test_case2';
    SELECT     ca.*, cu.*
    FROM ca_receipt CA,
         cu_all CU
    WHERE       CA.CUSTID = CU.CUSTID
    AND         CU.CUSTID IN (SELECT CUSTID FROM cu_all START WITH custid = 2353
                  CONNECT BY PRIOR CUSTID = CANO)
    ORDER BY ACCTYPE DESC;
    Execution Plan
    Plan hash value: 497148844
    | Id  | Operation                           | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                    |                       |  1001 | 81081 |   136   (3)| 00:00:01 |
    |   1 |  SORT ORDER BY                      |                       |  1001 | 81081 |   136   (3)| 00:00:01 |
    |   2 |   TABLE ACCESS BY INDEX ROWID       | CA_RECEIPT            |    50 |  1050 |    52   (0)| 00:00:01 |
    |   3 |    NESTED LOOPS                     |                       |  1001 | 81081 |   134   (2)| 00:00:01 |
    |   4 |     NESTED LOOPS                    |                       |    20 |  1200 |    43   (3)| 00:00:01 |
    |   5 |      VIEW                           | VW_NSO_1              |    20 |   100 |    22   (0)| 00:00:01 |
    |   6 |       HASH UNIQUE                   |                       |    20 |   180 |            |          |
    |*  7 |        CONNECT BY WITH FILTERING    |                       |       |       |            |          |
    |   8 |         TABLE ACCESS BY INDEX ROWID | CU_ALL                |     1 |    19 |     2   (0)| 00:00:01 |
    |*  9 |          INDEX UNIQUE SCAN          | PK_CU_ALL_IND         |     1 |       |     1   (0)| 00:00:01 |
    |  10 |         NESTED LOOPS                |                       |       |       |            |          |
    |  11 |          CONNECT BY PUMP            |                       |       |       |            |          |
    |  12 |          TABLE ACCESS BY INDEX ROWID| CU_ALL                |    20 |   180 |    22   (0)| 00:00:01 |
    |* 13 |           INDEX RANGE SCAN          | IND2_CU_ALL           |    20 |       |     1   (0)| 00:00:01 |
    |  14 |      TABLE ACCESS BY INDEX ROWID    | CU_ALL                |     1 |    55 |     1   (0)| 00:00:01 |
    |* 15 |       INDEX UNIQUE SCAN             | PK_CU_ALL_IND         |     1 |       |     0   (0)| 00:00:01 |
    |* 16 |     INDEX RANGE SCAN                | IND_CA_RECEIPT_CUSTID |    50 |    |     2   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       7 - access("CANO"=PRIOR "CUSTID")
       9 - access("CUSTID"=2353)
      13 - access("CANO"=PRIOR "CUSTID")
      15 - access("CU"."CUSTID"="$nso_col_1")
      16 - access("CA"."CUSTID"="CU"."CUSTID")
    Statistics
              1  recursive calls
              0  db block gets
            162  consistent gets
              0  physical reads
              0  redo size
           2302  bytes sent via SQL*Net to client
            379  bytes received via SQL*Net from client
              5  SQL*Net roundtrips to/from client
              5  sorts (memory)
              0  sorts (disk)
             52  rows processed
    ALTER SESSION SET EVENTS '10053 trace name context off';The question might be asked, does the final SQL statement actually executed look the same as the original? Slightly reformatted:
    The first SQL statement:
    SELECT
      CA.*,
      CU.*
    FROM
      CA_RECEIPT CA,
      CU_ALL CU
    WHERE
      CA.CUSTID = CU.CUSTID
      AND CA.CUSTID IN (
        SELECT
          CUSTID
        FROM
          CU_ALL
        START WITH
          CUSTID = 2353
        CONNECT BY PRIOR
          CUSTID = CANO)
    ORDER BY
      ACCTYPE DESC;
    Final Transformation:
    SELECT
      "CA"."CUSTID" "CUSTID",
      "CA"."CAAMT" "CAAMT",
      "CA"."CADT" "CADT",
      "CA"."TOTBAL" "TOTBAL",
      "CU"."CUSTID" "CUSTID",
      "CU"."ADDR" "ADDR",
      "CU"."PH" "PH",
      "CU"."CANO" "CANO",
      "CU"."ACCTYPE" "ACCTYPE"
    FROM
      (SELECT DISTINCT
        "CU_ALL"."CUSTID" "$nso_col_1"
      FROM
        "TESTUSER"."CU_ALL" "CU_ALL"
      WHERE
        "CU_ALL"."CANO"=PRIOR "CU_ALL"."CUSTID"
      CONNECT BY
        "CU_ALL"."CANO"=PRIOR "CU_ALL"."CUSTID") "VW_NSO_1",
      "TESTUSER"."CA_RECEIPT" "CA",
      "TESTUSER"."CU_ALL" "CU"
    WHERE
      "CA"."CUSTID"="VW_NSO_1"."$nso_col_1"
      AND "CA"."CUSTID"="CU"."CUSTID"
    ORDER BY
      "CU"."ACCTYPE" DESC;The second SQL statement:
    SELECT
      CA.*,
      CU.*
    FROM
      CA_RECEIPT CA,
      CU_ALL CU
    WHERE
      CA.CUSTID = CU.CUSTID
      AND CU.CUSTID IN (
        SELECT
          CUSTID
        FROM
          CU_ALL
        START WITH
          CUSTID = 2353
        CONNECT BY PRIOR
          CUSTID = CANO)
    ORDER BY
      ACCTYPE DESC;
    Final Transformation:
    SELECT
      "CA"."CUSTID" "CUSTID",
      "CA"."CAAMT" "CAAMT",
      "CA"."CADT" "CADT",
      "CA"."TOTBAL" "TOTBAL",
      "CU"."CUSTID" "CUSTID",
      "CU"."ADDR" "ADDR",
      "CU"."PH" "PH",
      "CU"."CANO" "CANO",
      "CU"."ACCTYPE" "ACCTYPE"
    FROM
      (SELECT DISTINCT
        "CU_ALL"."CUSTID" "$nso_col_1"
      FROM
        "TESTUSER"."CU_ALL" "CU_ALL"
      WHERE
        "CU_ALL"."CANO"=PRIOR "CU_ALL"."CUSTID"
      CONNECT BY
        "CU_ALL"."CANO"=PRIOR "CU_ALL"."CUSTID") "VW_NSO_1",
      "TESTUSER"."CA_RECEIPT" "CA",
      "TESTUSER"."CU_ALL" "CU"
    WHERE
      "CA"."CUSTID"="CU"."CUSTID"
      AND "CU"."CUSTID"="VW_NSO_1"."$nso_col_1"
    ORDER BY
      "CU"."ACCTYPE" DESC;Now, let's take a look at performance, flushing the buffer cache to force physical reads:
    SET AUTOTRACE OFF
    SET TIMING ON
    SET AUTOTRACE TRACEONLY STATISTICS
    SET ARRAYSIZE 100
    ALTER SYSTEM FLUSH BUFFER_CACHE;
    ALTER SYSTEM FLUSH BUFFER_CACHE;
    SELECT
      CA.*,
      CU.*
    FROM
      CA_RECEIPT CA,
      CU_ALL CU
    WHERE
      CA.CUSTID = CU.CUSTID
      AND CA.CUSTID IN (
        SELECT
          CUSTID
        FROM
          CU_ALL
        START WITH
          CUSTID = 2353
        CONNECT BY PRIOR
          CUSTID = CANO)
    ORDER BY
      ACCTYPE DESC;
    ALTER SYSTEM FLUSH BUFFER_CACHE;
    ALTER SYSTEM FLUSH BUFFER_CACHE;
    SELECT
      CA.*,
      CU.*
    FROM
      CA_RECEIPT CA,
      CU_ALL CU
    WHERE
      CA.CUSTID = CU.CUSTID
      AND CU.CUSTID IN (
        SELECT
          CUSTID
        FROM
          CU_ALL
        START WITH
          CUSTID = 2353
        CONNECT BY PRIOR
          CUSTID = CANO)
    ORDER BY
      ACCTYPE DESC;The output:
    /* (with AND CA.CUSTID IN...) */
    52 rows selected.
    Elapsed: 00:00:00.64
    Statistics
              0  recursive calls
              0  db block gets
            232  consistent gets
            592  physical reads
              0  redo size
           2044  bytes sent via SQL*Net to client
            346  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              5  sorts (memory)
              0  sorts (disk)
             52  rows processed
    /* (with AND CU.CUSTID IN...) */
    52 rows selected.
    Elapsed: 00:00:00.70
    Statistics
              0  recursive calls
              0  db block gets
            162  consistent gets
            712  physical reads
              0  redo size
           2044  bytes sent via SQL*Net to client
            346  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              5  sorts (memory)
              0  sorts (disk)
             52  rows processedThe original SQL statement completed in 0.64 seconds, and the second completed in 0.70 seconds.
    Charles Hooper
    IT Manager/Oracle DBA
    K&M Machine-Fabricating, Inc.

  • CBO refuses hint (sometimes)

    Sometimes, the CBO does not take hints. Can anyone explain it?
    SQL:
    SELECT * FROM v_osi_child v1 WHERE mainuuid IN (SELECT uuid FROM ot_sys_index_org v2 WHERE mainuuid IN(:p1))v_osi_child is a view which union-alls about 50 tables. ot_sys_index_org is here only used for getting some mainuuids.
    The statement itself is free of sense :)
    Explain plan:
    | Id  | Operation            | Name                    | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |                         |     4 | 17252 |   402K  (1)| 01:20:31 |
    |*  1 |  HASH JOIN           |                         |     4 | 17252 |   402K  (1)| 01:20:31 |
    |*  2 |   INDEX RANGE SCAN   | PK_OTSYSINDEX           |     4 |   340 |     4   (0)| 00:00:01 |
    |   3 |   VIEW               | V_OSI_CHILD             |    56M|   223G|   402K  (1)| 01:20:27 |
    |   4 |    UNION-ALL         |                         |       |       |            |          |
    |   5 |     TABLE ACCESS FULL| FL_ALLG_BENUTZERDATEN   | 16797 |  1295K|   105   (0)| 00:00:02 |
    |   6 |     TABLE ACCESS FULL| FL_BERATUNG             |    17 |  1343 |     3   (0)| 00:00:01 |
    |   7 |     TABLE ACCESS FULL| PA_KBIVBI               | 16797 |  1295K|   105   (0)| 00:00:02 |
    ...This statement needs more than 10 minutes.
    Inserting a hint:
    SELECT /*+ push_pred(v1) */ * FROM v_osi_child v1 WHERE mainuuid IN (SELECT uuid FROM ot_sys_index_org v2 WHERE mainuuid IN(:p1));Explain plan:
    | Id  | Operation                      | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT               |                            |     4 | 17852 | 12747   (1)| 00:02:33 |
    |   1 |  NESTED LOOPS                  |                            |     4 | 17852 | 12747   (1)| 00:02:33 |
    |*  2 |   INDEX RANGE SCAN             | PK_OTSYSINDEX              |     4 |   532 |     4   (0)| 00:00:01 |
    |   3 |   VIEW                         | V_OSI_CHILD                |     1 |  4330 |  3186   (1)| 00:00:39 |
    |   4 |    UNION ALL PUSHED PREDICATE  |                            |       |       |            |          |
    |   5 |     TABLE ACCESS BY INDEX ROWID| FL_ALLG_BENUTZERDATEN      |     1 |    79 |     2   (0)| 00:00:01 |
    |*  6 |      INDEX RANGE SCAN          | OSI_FLALLGBENUTZE_MAINUUID |     1 |       |     1   (0)| 00:00:01 |
    |   7 |     TABLE ACCESS BY INDEX ROWID| FL_BERATUNG                |     1 |    79 |     2   (0)| 00:00:01 |
    |*  8 |      INDEX RANGE SCAN          | OSI_FLBERATUNG_MAINUUID    |     1 |       |     1   (0)| 00:00:01 |
    |   9 |     TABLE ACCESS BY INDEX ROWID| PA_KBIVBI                  |     1 |    79 |     2   (0)| 00:00:01 |
    |* 10 |      INDEX RANGE SCAN          | OSI_PAKBIVBI_MAINUUID      |     1 |       |     1   (0)| 00:00:01 |
    |  11 |     TABLE ACCESS BY INDEX ROWID| FL_K_AKTIVITAET            |     1 |   100 |     2   (0)| 00:00:01 |
    |* 12 |      INDEX RANGE SCAN          | OSI_FLKAKTIVITAET_MAINUUID |     1 |       |     1   (0)| 00:00:01 |
    ...Well, using the index on mainuuids is realy a good idea, if the estimated resultset of the subquery are about 4 rows.
    Costs are decreased from 402k to 12747.
    Query runs in a second.
    Now, lets modify the subquery a little bit. Again, the estimated result of the subquery are 4 rows:
    SELECT * FROM v_osi_child v1 WHERE mainuuid IN (SELECT mainuuid FROM ot_sys_index_org v2 WHERE value IN(:p1));Explain plan:
    | Id  | Operation            | Name                    | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |                         |     4 | 17104 |   402K  (1)| 01:20:31 |
    |*  1 |  HASH JOIN RIGHT SEMI|                         |     4 | 17104 |   402K  (1)| 01:20:31 |
    |*  2 |   INDEX RANGE SCAN   | IX_OT_SYS_INDEX01       |     4 |   192 |     5   (0)| 00:00:01 |
    |   3 |   VIEW               | V_OSI_CHILD             |    56M|   223G|   402K  (1)| 01:20:27 |
    |   4 |    UNION-ALL         |                         |       |       |            |          |
    |   5 |     TABLE ACCESS FULL| FL_ALLG_BENUTZERDATEN   | 16797 |  1295K|   105   (0)| 00:00:02 |
    |   6 |     TABLE ACCESS FULL| FL_BERATUNG             |    17 |  1343 |     3   (0)| 00:00:01 |
    |   7 |     TABLE ACCESS FULL| PA_KBIVBI               | 16797 |  1295K|   105   (0)| 00:00:02 |
    |   8 |     TABLE ACCESS FULL| FL_K_AKTIVITAET         |    26 |  2600 |     3   (0)| 00:00:01 |
    ...Well, almost the same values...
    Now, use the same hint:
    SELECT /*+ push_pred(v1) */ * FROM v_osi_child v1 WHERE mainuuid IN (SELECT mainuuid FROM ot_sys_index_org v2 WHERE value IN(:p1));Explain plan:
    | Id  | Operation            | Name                    | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |                         |     4 | 17104 |   402K  (1)| 01:20:31 |
    |*  1 |  HASH JOIN RIGHT SEMI|                         |     4 | 17104 |   402K  (1)| 01:20:31 |
    |*  2 |   INDEX RANGE SCAN   | IX_OT_SYS_INDEX01       |     4 |   192 |     5   (0)| 00:00:01 |
    |   3 |   VIEW               | V_OSI_CHILD             |    56M|   223G|   402K  (1)| 01:20:27 |
    |   4 |    UNION-ALL         |                         |       |       |            |          |
    |   5 |     TABLE ACCESS FULL| FL_ALLG_BENUTZERDATEN   | 16797 |  1295K|   105   (0)| 00:00:02 |
    |   6 |     TABLE ACCESS FULL| FL_BERATUNG             |    17 |  1343 |     3   (0)| 00:00:01 |
    |   7 |     TABLE ACCESS FULL| PA_KBIVBI               | 16797 |  1295K|   105   (0)| 00:00:02 |
    ...Nothing has changed.
    I can't explain it. It seems to be an oracle-bug...
    Release: 11.1.0.7.0 - 64bit Production
    OS: RHEL 5.3

    Ulrich Weiss wrote:
    All this is readable from the explain plans.I don't know the reason behind this behaviour and I don't have a 11g version to test on, but I found similar observations on a 10g database. A small yet complete reproducible test case always helps. Here is mine:
    SQL> select * from v$version ;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
    PL/SQL Release 10.2.0.4.0 - Production
    CORE     10.2.0.4.0     Production
    TNS for Solaris: Version 10.2.0.4.0 - Production
    NLSRTL Version 10.2.0.4.0 - Production
    SQL> drop view v_t ;
    View dropped.
    SQL> drop table t1 purge ;
    Table dropped.
    SQL> drop table t purge ;
    Table dropped.
    SQL> create table t nologging as select * from all_objects ;
    Table created.
    SQL> create table t1 nologging as select * from t where rownum <= 1000 ;
    Table created.
    SQL> create or replace view v_t as
      2  select * from t where object_type = 'PACKAGE'
      3  union all
      4  select * from t where object_type = 'PACKAGE BODY' ;
    View created.
    SQL> explain plan for select * from v_t where object_id in (select object_id from t1 where owner = '
      2  SYS') ;
    Explained.
    SQL> exec dbms_stats.gather_table_stats(user, 'T') ;
    PL/SQL procedure successfully completed.
    SQL> exec dbms_stats.gather_table_stats(user, 'T1') ;
    PL/SQL procedure successfully completed.
    SQL> explain plan for select * from v_t where object_id in (select object_id from t1 where owner = 'SYS') ;
    Explained.
    SQL> select * from table(dbms_xplan.display) ;
    PLAN_TABLE_OUTPUT
    Plan hash value: 443534535
    | Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |      |     2 |   274 |   333   (2)| 00:00:04 |
    |*  1 |  HASH JOIN RIGHT SEMI|      |     2 |   274 |   333   (2)| 00:00:04 |
    |*  2 |   TABLE ACCESS FULL  | T1   |   893 |  8037 |     5   (0)| 00:00:01 |
    |   3 |   VIEW               | V_T  |  2055 |   256K|   327   (2)| 00:00:04 |
    |   4 |    UNION-ALL         |      |       |       |            |          |
    |*  5 |     TABLE ACCESS FULL| T    |  1067 |    97K|   164   (2)| 00:00:02 |
    |*  6 |     TABLE ACCESS FULL| T    |   988 | 92872 |   164   (2)| 00:00:02 |
    Predicate Information (identified by operation id):
       1 - access("OBJECT_ID"="OBJECT_ID")
       2 - filter("OWNER"='SYS')
       5 - filter("OBJECT_TYPE"='PACKAGE')
       6 - filter("OBJECT_TYPE"='PACKAGE BODY')
    21 rows selected.
    SQL> explain plan for select /*+ push_pred(v_t) */ * from v_t where object_id in (select object_id from t1 where owner = 'SYS') ;
    Explained.
    SQL> select * from table(dbms_xplan.display) ;
    PLAN_TABLE_OUTPUT
    Plan hash value: 443534535
    | Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |      |     2 |   274 |   333   (2)| 00:00:04 |
    |*  1 |  HASH JOIN RIGHT SEMI|      |     2 |   274 |   333   (2)| 00:00:04 |
    |*  2 |   TABLE ACCESS FULL  | T1   |   893 |  8037 |     5   (0)| 00:00:01 |
    |   3 |   VIEW               | V_T  |  2055 |   256K|   327   (2)| 00:00:04 |
    |   4 |    UNION-ALL         |      |       |       |            |          |
    |*  5 |     TABLE ACCESS FULL| T    |  1067 |    97K|   164   (2)| 00:00:02 |
    |*  6 |     TABLE ACCESS FULL| T    |   988 | 92872 |   164   (2)| 00:00:02 |
    Predicate Information (identified by operation id):
       1 - access("OBJECT_ID"="OBJECT_ID")
       2 - filter("OWNER"='SYS')
       5 - filter("OBJECT_TYPE"='PACKAGE')
       6 - filter("OBJECT_TYPE"='PACKAGE BODY')
    21 rows selected.
    SQL> explain plan for select v_t.* from v_t, t1 where v_t.object_id = t1.object_id and t1.owner = 'SYS' ;
    Explained.
    SQL> select * from table(dbms_xplan.display) ;
    PLAN_TABLE_OUTPUT
    Plan hash value: 2725479221
    | Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |      |  1834 |   245K|   333   (2)| 00:00:04 |
    |*  1 |  HASH JOIN           |      |  1834 |   245K|   333   (2)| 00:00:04 |
    |*  2 |   TABLE ACCESS FULL  | T1   |   893 |  8037 |     5   (0)| 00:00:01 |
    |   3 |   VIEW               | V_T  |  2055 |   256K|   327   (2)| 00:00:04 |
    |   4 |    UNION-ALL         |      |       |       |            |          |
    |*  5 |     TABLE ACCESS FULL| T    |  1067 |    97K|   164   (2)| 00:00:02 |
    |*  6 |     TABLE ACCESS FULL| T    |   988 | 92872 |   164   (2)| 00:00:02 |
    Predicate Information (identified by operation id):
       1 - access("V_T"."OBJECT_ID"="T1"."OBJECT_ID")
       2 - filter("T1"."OWNER"='SYS')
       5 - filter("OBJECT_TYPE"='PACKAGE')
       6 - filter("OBJECT_TYPE"='PACKAGE BODY')
    21 rows selected.
    SQL> explain plan for select /*+ push_pred(v_t) */ v_t.* from v_t, t1 where v_t.object_id = t1.object_id and t1.owner = 'SYS' ;
    Explained.
    SQL> select * from table(dbms_xplan.display) ;
    PLAN_TABLE_OUTPUT
    Plan hash value: 3926093524
    | Id  | Operation                     | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT              |      |  1834 |   263K|   292K  (2)| 00:58:28 |
    |   1 |  NESTED LOOPS                 |      |  1834 |   263K|   292K  (2)| 00:58:28 |
    |*  2 |   TABLE ACCESS FULL           | T1   |   893 | 11609 |     5   (0)| 00:00:01 |
    |   3 |   VIEW                        | V_T  |     1 |   134 |   327   (2)| 00:00:04 |
    |   4 |    UNION ALL PUSHED PREDICATE |      |       |       |            |          |
    |*  5 |     TABLE ACCESS FULL         | T    |     1 |    94 |   164   (2)| 00:00:02 |
    |*  6 |     TABLE ACCESS FULL         | T    |     1 |    94 |   164   (2)| 00:00:02 |
    Predicate Information (identified by operation id):
       2 - filter("T1"."OWNER"='SYS')
       5 - filter("OBJECT_ID"="T1"."OBJECT_ID" AND "OBJECT_TYPE"='PACKAGE')
       6 - filter("OBJECT_ID"="T1"."OBJECT_ID" AND "OBJECT_TYPE"='PACKAGE BODY')
    20 rows selected.As you can see, the PUSH_PRED hint is ignored when I use the IN clause with subquery.
    I believe this is same as what you are experiencing. However, when I change the sql to use
    a JOIN (instead of subquery), the hint is not ignored.
    p.s. I hope my JOIN query is semantically equivalent to IN..SUBQUERY.

  • CBO calculates un acceptable cost while using index.

    Hi,
    I was wondering to see the execution plan for both the case using index/without index.
    We are using oracle 10G(10.2.0.3.0) with RAC in production at O/S:- sun solaris 10.
    Java based application is running in this database. One of the sql query is taking long time to fetch the records. I analyzed the sql plan and noticed the FTS. I created indexes to the column(s) which is refering in where clauses. I noticed a strage behavior. Execution plan shows that the CBO is using right path but its not acceptable as application is time outs while return the rows.
    first execution plan with/without index (not using the index).
    PLAN_TABLE_OUTPUT
    Plan hash value: 419342726
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 196 | 3332 | 67845 (3)| 00:13:35 |
    |* 1 | TABLE ACCESS FULL | CWDBENUMDESCRIPTIONS | 1 | 35 | 3 (0)| 00:00:01 |
    | 2 | SORT GROUP BY | | 196 | 3332 | 67845 (3)| 00:13:35 |
    |* 3 | TABLE ACCESS FULL| CWORDERINSTANCE | 51466 | 854K| 67837 (3)| 00:13:35 |
    Predicate Information (identified by operation id):
    1 - filter("ERR"."CODE"=:B1)
    3 - filter("OI"."ERROR_CODE" IS NOT NULL AND "OI"."DIVISION"='OR9' AND
    "OI"."ACTIVE"=TO_NUMBER(:1) AND "OI"."ORDER_STATE"<>'O_NR_NS' AND
    "OI"."ORDER_STATE"<>'C_C_QR' AND "OI"."ORDER_STATE"<>'O_NR_NS_D')
    SQl query was modified to force the index to use /*+ index(oi oi_div) */ the execution is as below:-
    PLAN_TABLE_OUTPUT
    Plan hash value: 1157277132
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 196 | 3332 | 394K (1)| 01:18:52 |
    |* 1 | TABLE ACCESS FULL | CWDBENUMDESCRIPTIONS | 1 | 35 | 3 (0)| 00:00:01 |
    | 2 | SORT GROUP BY | | 196 | 3332 | 394K (1)| 01:18:52 |
    |* 3 | TABLE ACCESS BY INDEX ROWID| CWORDERINSTANCE | 51466 | 854K| 394K (1)| 01:18:52 |
    |* 4 | INDEX RANGE SCAN | OI_DIV | 3025K| | 14226 (1)| 00:02:51 |
    Predicate Information (identified by operation id):
    1 - filter("ERR"."CODE"=:B1)
    3 - filter("OI"."ERROR_CODE" IS NOT NULL AND "OI"."ACTIVE"=TO_NUMBER(:1) AND
    "OI"."ORDER_STATE"<>'O_NR_NS' AND "OI"."ORDER_STATE"<>'C_C_QR' AND
    "OI"."ORDER_STATE"<>'O_NR_NS_D')
    My questions are here:-
    1). why FTS is less costly comparing index scan where there are 15000000 rows in the table.
    2). while forcing index to use cost increase drastically (the statistics is latest one analyzed on 6th of feb 2009)
    3). what should i suppose to change to get the performance benefit.
    Thanks,
    Pradeep

    user587112 wrote:
    select null, oi.division, oi.METADATATYPE, oi.ERROR_CODE,
           (  select err.DESCRIPTION
    FROM   CWDBENUMDESCRIPTIONS err
    WHERE  oi.ERROR_CODE = err.CODE
    count(*)
    from CWORDERINSTANCE oi
    where
         oi.ERROR_CODE is not null
          and oi.division in ('BK9')
         and oi.order_state not in ('O_NR_NS_D', 'C_C_QR', 'O_NR_NS')
          and oi.metadatatype = :1
         and oi.duedate>=:2
         and oi.active = :3
    group by oi.division, oi.metadatatype, oi.error_code
    order by oi.division, oi.metadatatype, oi.error_code
    In this query, if we use as it is how its being displayed, it runs like a rocket, but if we change division in ('OR9') instead of 'BK9' it does not use index and leads to time out the application.
    Number of records   division
    1964690                             ---------------- why this field is null ?
    3090666              OR9
    3468                 BA9
    1242                 EL9
    2702                 IN9
    258                  EU9
    196198               DT9
    1268                 PA9
    8                    BK9
    2332                 BH9
    1405009              TP9
    According to the stats in your original execution plan, it looks like you have a histogram on this column, and the index you want to use is on just the division column.
    Oracle estimate for 'OR9' is 3M rowids from the index, resulting in 50,000+ rows from the table - that's a lot of work - it's not surprising that the optimizer chose a tablescan for 'OR9' - but chose to use the index for 'BK9' which has only 8 rows.
    How often do you want to run this query ? And how accurate does the answer have to be ?
    If you want this query to run faster even when it's processing a huge number of rows, one option would be to create a materialized view over the data that could supply the result set much more efficiently (possibly getting your front-end code to call a materialized view refresh before running the query).
    The only other altenative is probably to create an index that covers all the columns in the query so that you don't have to visit the table - and if you order them correctly you won't have to do a sort group by. I think this index should do the trick: (division, metadatatype, error_code,active, duedate,orderstate). You could also compress this index on at least the first column, but possibly on far more columns, to minimise the size,
    Regards
    Jonathan Lewis
    http://jonathanlewis.wordpress.com
    http://www.jlcomp.demon.co.uk
    "The greatest enemy of knowledge is not ignorance, it is the illusion of knowledge."
    Stephen Hawking
    To post code, statspack/AWR report, execution plans or trace files, start and end the section with the tag {noformat}{noformat} (lowercase, curly brackets, no spaces) so that the text appears in fixed format.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

  • Tuning of a view

    Hi,
    Below is the view used in cursor with order by clause. Its taking lot of time for teching rows.
    Could anyone help to tune this view. so that performace can be improved.
    If I remove rule based optimzer hint and checked explain plan for CBO. Its doing many full table scans and also its kaing more time then rule based.
    CREATE OR REPLACE VIEW V_FIF AS
    SELECT  /*+ rule */
            ml_level_type                   fif_ml,
            ifs.if_ml_id                    fif_ml_id,
            ifs.if_id                       fif_if_id,
            ifs.if_type                     fif_if_type,
            ifs.if_min_stock_level          fif_min_stock_level,
            ifs.if_max_stock_level          fif_max_stock_level,
            ifs.if_mi_id                    fif_mi_id,
            ifs.if_std_produced_qty         fif_if_std_produced_qty,
            ifs.if_lotsize                  fif_if_lotsize,
            ifs.if_successor_qty            fif_successor_qty,
            ifs.if_successor_base_qty       fif_successor_base_qty,
            ifs.if_successor_uom            fif_successor_uom,
            ifs.if_if_id                    fif_if_if_id,
            ifs.if_valid_flag               fif_valid_flag,
            ifs.if_freeze_fence             fif_freeze_fence,
            ifs.if_freeze_fence_date        fif_freeze_fence_date,
            ifs.if_freeze_fence_date_old    fif_freeze_fence_date_old,
            ifs.if_facility_planning_flag   fif_facility_planning_flag,
            ifs.if_deletion_mark            fif_if_deletion_mark,
         ifs.if_allocation_fence_date     fif_allocation_fence_date,
            ifs.misr_id                     fif_misr_id,
            ifs.misr_me_id                  fif_me_id,
            ifs.item_mat_id                 fif_item_mat_id,
            ifs.item_prit_id                fif_item_prit_id,
            ifs.item_papl_id                fif_item_papl_id,
            ifs.item_repi_id                fif_item_repi_id,
            ifs.item_tnr                    fif_item_tnr,
            ifs.item_id                     fif_item_id,
            ifs.btyp_id                     fif_btyp_id,
            ifs.btyp_basic_type             fif_basic_type,
            sprd_sales_name                 fif_sprd_sales_name,
            bno_id                          fif_bno_id,
            bno_baunumber                   fif_bno,
            bno_deletion_mark               fif_bno_deletion_mark,
            bno_demand_level_code           fif_bno_demand_level_code,
            pg_id                           fif_pg_id,
            pl_process_line                 fif_pl_process_line,
            pl_id                           fif_pl_id,
            pcl_process_class               fif_pcl_process_class,
            pcl_id                          fif_pcl_id,
            pgp_id                          fif_pgp_id,
            DECODE(bs1.bs_id, NULL,DECODE(bs2.bs_id, NULL, bs3.bs_id, bs2.bs_id), bs1.bs_id)        fif_bs_id,
            DECODE(bs1.bs_business_segment, NULL,
                    DECODE(bs2.bs_business_segment, NULL, bs3.bs_business_segment, bs2.bs_business_segment), bs1.bs_business_segment) fif_bs_business_segment,
            fac_id                          fif_fac_id,
            fac_facility_name               fif_fac_name,
            fac_facility_type               fif_fac_type,
            fac_usable_from                 fif_fac_usable_from,
            fac_usable_to                   fif_fac_usable_to,
            fac_loc_id                      fif_fac_loc_id,
            loc_location                    fif_fac_loc_location,
            si1.site_id                     fif_site_id,
            si1.site_site_name              fif_site_name,
            si2.site_id                     fif_site_id_fm,
            si2.site_site_name              fif_site_name_fm,
            sc1.sc_id                       fif_sc_id,
            sc1.sc_supply_chain_name        fif_sc_name,
            sc1.sc_type                     fif_sc_type,
            sc1.sc_eng_id                   fif_sc_eng_id,
            sc2.sc_id                       fif_sc_id_fm,
            sc2.sc_supply_chain_name        fif_sc_name_fm,
            sc2.sc_type                     fif_sc_type_fm,
            sc2.sc_eng_id                   fif_sc_eng_id_fm,
            pk_id                           fif_pk_id,
            pk_package_name                 fif_package_name,
            eng_ignore_key_wc               fif_eng_ignore_key_wc,
            dbi_id                          fif_dbi_id,
            bno_rias_user                   fif_bno_rias_user,
            bno_production_arranger         fif_bno_production_arranger
          , if_merchandise_flag             fif_merchandise_flag
    FROM
            (SELECT
                    ifsel.*,
                    misr_id,
                    misr_me_id,
                    item_mat_id,
                    item_prit_id,
                    item_papl_id,
                    item_repi_id,
                    item_tnr,
                    item_id,
                    item_sisc_id,
                    me_pk_id,
                    decode (if_misr_id, null, nvl(btyp2.btyp_id,0), btyp1.btyp_id)                          btyp_id,
                    decode (if_misr_id, null, nvl(btyp2.btyp_basic_type, 'UNDEF.'), btyp1.btyp_basic_type)  btyp_basic_type,
                    decode (if_misr_id, null, nvl(btyp2.btyp_pl_id, 0), btyp1.btyp_pl_id)                   btyp_pl_id
            FROM
                    basic_types     btyp1,
                    basic_types     btyp2,
                    processed_items,
                    items,
                    mi_subroutes,
                    mi_elements,
                    item_facilities ifsel
            WHERE
                        ifsel.if_item_id = item_id
                    AND ifsel.if_misr_id = misr_id(+)
                    AND item_prit_id = prit_id (+)
                    AND prit_btyp_id = btyp2.btyp_id (+)
                    AND misr_me_id = me_id(+)
                    AND me_btyp_id = btyp1.btyp_id(+)
                    AND ifsel.if_type <> 'K'
                    AND
                               (item_prit_id is not null
                            OR item_repi_id is not null
                            OR item_sisc_id is not null)) ifs,
            manufacturing_levels,
            start_item_scs,
            business_segments bs3,
            sites si1,
            supply_chains sc1,
            sites si2,
            supply_chains sc2,
            engines,
            database_instances,
            facilities,
            locations,
            packages,
            representative_items,
            business_segments bs2,
            process_lines,
            process_groups,
            process_classes,
            baunumbers,
            product_groups,
            business_segments bs1,
            sales_products
    WHERE
                ifs.if_ml_id = ml_id
            AND ml_level_type <> 'UNDEF'
            AND ifs.item_sisc_id  = sisc_id(+)
            AND sisc_bs_id = bs3.bs_id(+)
            AND ifs.if_site_id = si1.site_id(+)
            AND si1.site_sc_id = sc1.sc_id(+)
            AND si1.site_site_id = si2.site_id(+)
            AND si2.site_sc_id = sc2.sc_id(+)
            AND sc2.sc_eng_id = eng_id(+)
            AND eng_dbi_id = dbi_id(+)
            AND ifs.if_fac_id = fac_id
            AND fac_loc_id = loc_id
            AND ifs.me_pk_id = pk_id(+)
            AND ifs.item_repi_id = repi_id(+)
            AND repi_bs_id = bs2.bs_id(+)
            AND ifs.btyp_pl_id = pl_id(+)
            AND pl_pgp_id = pgp_id (+)
            AND pgp_pcl_id = pcl_id (+)
            AND ifs.if_bno_id = bno_id(+)
            AND bno_pg_id = pg_id(+)
            AND pg_bs_id = bs1.bs_id(+)
            AND ifs.if_bno_id = sprd_bno_id(+)
            AND (bs1.bs_id is not null OR bs2.bs_id is not null OR bs3.bs_id is not null)
            AND (bno_baunumber is not null OR ifs.item_tnr is not null)
            AND (bno_deletion_mark is null OR ml_level_type = 'VKL')
    Explain plan for select * from v_fif order by fif_if_id;
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    Plan hash value: 62762906
    | Id  | Operation                                                 | Name
    |   0 | SELECT STATEMENT                                          |
    |   1 |  SORT ORDER BY                                            |
    |   2 |   NESTED LOOPS                                            |
    |*  3 |    FILTER                                                 |
    |   4 |     NESTED LOOPS OUTER                                    |
    |   5 |      NESTED LOOPS OUTER                                   |
    |   6 |       NESTED LOOPS OUTER                                  |
    |   7 |        NESTED LOOPS OUTER                                 |
    |   8 |         NESTED LOOPS OUTER                                |
    |   9 |          NESTED LOOPS OUTER                               |
    |  10 |           NESTED LOOPS OUTER                              |
    |  11 |            NESTED LOOPS OUTER                             |
    |  12 |             NESTED LOOPS                                  |
    |  13 |              NESTED LOOPS                                 |
    |  14 |               NESTED LOOPS OUTER                          |
    PLAN_TABLE_OUTPUT
    |  15 |                NESTED LOOPS OUTER                         |
    |  16 |                 NESTED LOOPS OUTER                        |
    |  17 |                  NESTED LOOPS OUTER                       |
    |  18 |                   NESTED LOOPS OUTER                      |
    |  19 |                    NESTED LOOPS OUTER                     |
    |  20 |                     NESTED LOOPS OUTER                    |
    |  21 |                      NESTED LOOPS OUTER                   |
    |  22 |                       NESTED LOOPS OUTER                  |
    |  23 |                        NESTED LOOPS OUTER                 |
    |  24 |                         VIEW                              |
    |  25 |                          NESTED LOOPS OUTER               |
    |  26 |                           NESTED LOOPS OUTER              |
    |  27 |                            NESTED LOOPS OUTER             |
    |  28 |                             NESTED LOOPS                  |
    |  29 |                              NESTED LOOPS OUTER           |
    |  30 |                               NESTED LOOPS OUTER          |
    |* 31 |                                TABLE ACCESS FULL          | ITEM_FACILIT
    |  32 |                                TABLE ACCESS BY INDEX ROWID| MI_SUBROUTES
    |* 33 |                                 INDEX UNIQUE SCAN         | MISR_PK
    |  34 |                               TABLE ACCESS BY INDEX ROWID | MI_ELEMENTS
    |* 35 |                                INDEX UNIQUE SCAN          | ME_PK
    PLAN_TABLE_OUTPUT
    |* 36 |                              TABLE ACCESS BY INDEX ROWID  | ITEMS
    |* 37 |                               INDEX UNIQUE SCAN           | ITEM_PK
    |  38 |                             TABLE ACCESS BY INDEX ROWID   | PROCESSED_IT
    |* 39 |                              INDEX UNIQUE SCAN            | PRIT_PK
    |  40 |                            TABLE ACCESS BY INDEX ROWID    | BASIC_TYPES
    |* 41 |                             INDEX UNIQUE SCAN             | BTYP_PK
    |  42 |                           TABLE ACCESS BY INDEX ROWID     | BASIC_TYPES
    |* 43 |                            INDEX UNIQUE SCAN              | BTYP_PK
    |  44 |                         TABLE ACCESS BY INDEX ROWID       | SALES_PRODUC
    |* 45 |                          INDEX UNIQUE SCAN                | SPRD_SPRD1_U
    |  46 |                        TABLE ACCESS BY INDEX ROWID        | BAUNUMBERS
    |* 47 |                         INDEX UNIQUE SCAN                 | BNO_PK
    |  48 |                       TABLE ACCESS BY INDEX ROWID         | PRODUCT_GROU
    |* 49 |                        INDEX UNIQUE SCAN                  | PG_PK
    |  50 |                      TABLE ACCESS BY INDEX ROWID          | BUSINESS_SEG
    |* 51 |                       INDEX UNIQUE SCAN                   | BS_PK
    |  52 |                     TABLE ACCESS BY INDEX ROWID           | PROCESS_LINE
    |* 53 |                      INDEX UNIQUE SCAN                    | PL_PK
    |  54 |                    TABLE ACCESS BY INDEX ROWID            | PROCESS_GROU
    |* 55 |                     INDEX UNIQUE SCAN                     | PGP_PK
    |  56 |                   TABLE ACCESS BY INDEX ROWID             | PROCESS_CLAS
    PLAN_TABLE_OUTPUT
    |* 57 |                    INDEX UNIQUE SCAN                      | PCL_PK
    |  58 |                  TABLE ACCESS BY INDEX ROWID              | REPRESENTATI
    |* 59 |                   INDEX UNIQUE SCAN                       | REPI_PK
    |  60 |                 TABLE ACCESS BY INDEX ROWID               | BUSINESS_SEG
    |* 61 |                  INDEX UNIQUE SCAN                        | BS_PK
    |  62 |                TABLE ACCESS BY INDEX ROWID                | PACKAGES
    |* 63 |                 INDEX UNIQUE SCAN                         | PK_PK
    |  64 |               TABLE ACCESS BY INDEX ROWID                 | FACILITIES
    |* 65 |                INDEX UNIQUE SCAN                          | FAC_PK
    |  66 |              TABLE ACCESS BY INDEX ROWID                  | LOCATIONS
    |* 67 |               INDEX UNIQUE SCAN                           | LOC_PK
    |  68 |             TABLE ACCESS BY INDEX ROWID                   | SITES
    |* 69 |              INDEX UNIQUE SCAN                            | SITE_PK
    |  70 |            TABLE ACCESS BY INDEX ROWID                    | SITES
    |* 71 |             INDEX UNIQUE SCAN                             | SITE_PK
    |  72 |           TABLE ACCESS BY INDEX ROWID                     | SUPPLY_CHAIN
    |* 73 |            INDEX UNIQUE SCAN                              | SC_PK
    |  74 |          TABLE ACCESS BY INDEX ROWID                      | ENGINES
    |* 75 |           INDEX UNIQUE SCAN                               | ENG_PK
    |* 76 |         INDEX UNIQUE SCAN                                 | DBI_PK
    |  77 |        TABLE ACCESS BY INDEX ROWID                        | SUPPLY_CHAIN
    PLAN_TABLE_OUTPUT
    |* 78 |         INDEX UNIQUE SCAN                                 | SC_PK
    |  79 |       TABLE ACCESS BY INDEX ROWID                         | START_ITEM_S
    |* 80 |        INDEX UNIQUE SCAN                                  | SISC_PK
    |  81 |      TABLE ACCESS BY INDEX ROWID                          | BUSINESS_SEG
    |* 82 |       INDEX UNIQUE SCAN                                   | BS_PK
    |* 83 |    TABLE ACCESS BY INDEX ROWID                            | MANUFACTURIN
    |* 84 |     INDEX UNIQUE SCAN                                     | ML_PK
    Predicate Information (identified by operation id):
       3 - filter("BS1"."BS_ID" IS NOT NULL OR "BS2"."BS_ID" IS NOT NULL OR
                  "BS3"."BS_ID" IS NOT NULL)
      31 - filter("IFSEL"."IF_TYPE"<>'K')
      33 - access("IFSEL"."IF_MISR_ID"="MISR_ID"(+))
      35 - access("MISR_ME_ID"="ME_ID"(+))
      36 - filter("ITEM_PRIT_ID" IS NOT NULL OR "ITEM_REPI_ID" IS NOT NULL OR
                  "ITEM_SISC_ID" IS NOT NULL)
      37 - access("IFSEL"."IF_ITEM_ID"="ITEM_ID")
      39 - access("ITEM_PRIT_ID"="PRIT_ID"(+))
    PLAN_TABLE_OUTPUT
      41 - access("PRIT_BTYP_ID"="BTYP2"."BTYP_ID"(+))
      43 - access("ME_BTYP_ID"="BTYP1"."BTYP_ID"(+))
      45 - access("IFS"."IF_BNO_ID"="SPRD_BNO_ID"(+))
      47 - access("IFS"."IF_BNO_ID"="BNO_ID"(+))
      49 - access("BNO_PG_ID"="PG_ID"(+))
      51 - access("PG_BS_ID"="BS1"."BS_ID"(+))
      53 - access("IFS"."BTYP_PL_ID"="PL_ID"(+))
      55 - access("PL_PGP_ID"="PGP_ID"(+))
      57 - access("PGP_PCL_ID"="PCL_ID"(+))
      59 - access("IFS"."ITEM_REPI_ID"="REPI_ID"(+))
      61 - access("REPI_BS_ID"="BS2"."BS_ID"(+))
      63 - access("IFS"."ME_PK_ID"="PK_ID"(+))
      65 - access("IFS"."IF_FAC_ID"="FAC_ID")
      67 - access("FAC_LOC_ID"="LOC_ID")
      69 - access("IFS"."IF_SITE_ID"="SI1"."SITE_ID"(+))
      71 - access("SI1"."SITE_SITE_ID"="SI2"."SITE_ID"(+))
      73 - access("SI2"."SITE_SC_ID"="SC2"."SC_ID"(+))
      75 - access("SC2"."SC_ENG_ID"="ENG_ID"(+))
      76 - access("ENG_DBI_ID"="DBI_ID"(+))
      78 - access("SI1"."SITE_SC_ID"="SC1"."SC_ID"(+))
      80 - access("IFS"."ITEM_SISC_ID"="SISC_ID"(+))
    PLAN_TABLE_OUTPUT
      82 - access("SISC_BS_ID"="BS3"."BS_ID"(+))
      83 - filter(("BNO_DELETION_MARK" IS NULL OR "ML_LEVEL_TYPE"='VKL') AND
                  "ML_LEVEL_TYPE"<>'UNDEF')
      84 - access("IFS"."IF_ML_ID"="ML_ID")
    Note
       - rule based optimizer used (consider using cbo)
    133 rows selectedAny help really appreciated
    Thanks in advance

    I will suggest two things for your problem.
    1. Try to remove all the decode operation with case .
    2. If possible use CBO instead of RBO.
    As you said that CBO is taking more time .. You must gather statistics about the objects.
    and then use the CBO.
    And a full table scan not always stands for the performance problems.It depends on the cardinality of
    your SQL Statement.
    Your explain plan output also shows a view operation is taking place, so try to rewrite the view in some other
    possible way so that the view can become mergable with the main query.
    It will defenitely help you.
    Bi tc

  • Query can't be rewritten by a Materialized View

    Hi All,
    The structure of Materialized view looks like:
    select
    T1483342.MEASR_AMT as c4,
    T1482315.MTH_NAME as c8
    from
    MMM T1483380,
    AN_VSBL_IND_LKP T1483226,
    AMM T1484452 ,
    ND_ASDN_DIM T1483850,
    _FDIM                                    T1482018,
    R_DIM T1482315,
    AN_FCT T1483342
    where (JOINS)
    And it has 'ENABLE QUERY REWRITE' clause.
    If I run the query like this, the query rewritten is used by CBO and seems fine to me.
    select
    T1483342.MEASR_AMT as c4,
    T1482315.MTH_NAME as c8
    from
    MMM T1483380,
    AN_VSBL_IND_LKP T1483226,
    AMM T1484452 ,
    ND_ASDN_DIM T1483850,
    _FDIM                                   T1482018,
    R_DIM T1482315,
    AN_FCT T1483342
    where (JOINS)
    But if I run the query like the following one, query rewritten can't happen with the following reason:
    QSM-01072: materialized view, LEON_SVP_NEW1, and query have different joins between tables.
    select
    sum(T1483342.MEASR_AMT) as c4,
    T1482315.MTH_NAME as c8
    from
    MMM T1483380,
    AN_VSBL_IND_LKP T1483226,
    AMM T1484452 ,
    ND_ASDN_DIM T1483850,
    _FDIM                                          T1482018,
    R_DIM T1482315,
    AN_FCT T1483342
    where (JOINS)
    group by T1482315.MTH_NAME
    order by c8
    The only difference between the 2 query is one has aggregation on one column but the other does not.
    Can someone give me some advice on why the latter query is not rewritten by CBO, please?
    Thank you very much,
    Leon
    Edited by: user12064076 on Feb 15, 2011 7:22 PM

    The error message is
    QSM-01072: materialized view, string, and query have different joins between tables, string
    Cause: Anchors, if any, in the MV and query match. But the joins between these anchors in the MV and query are different.
    Action: None
    That would mean that the JOINs are different.
    Edited by: Hemant K Chitale on Feb 16, 2011 11:34 AM
    Edited by: Hemant K Chitale on Feb 16, 2011 11:34 AM

  • Materialized View Not Picked Up

    Hopefully I'm doing something wrong, because so far
    Materialized Views are useless. What's happening
    is that the MV is only picked up by a select
    statement when the select is identical to the MV
    query - this means that we'd have to create a
    separate MV for each possible query.
    Here's an example:
    create materialized view
    FACT_DIM04_LVL02
    enable query rewrite
    as
    select
    d04.DKEY
    , d04.LVL02_DESCR
    , f.KEY01
    , f.KEY03
    , f.YEAR_MONTH
    , f.SCENARIO
    , sum(f.AMOUNT) "AMOUNT"
    from FACT1 f
    , DIM04 d04
    where (f.KEY04 = d04.KEY04)
    and (f.ATTR01 = 'O')
    and (d04.LVL01_DESCR = '9999')
    and (f.SCENARIO IN ('ACT', 'PLAN'))
    group by
    d04.DKEY
    , d04.LVL02_DESCR
    , f.KEY01
    , f.KEY03
    , f.YEAR_MONTH
    , f.SCENARIO
    analyze table FACT_DIM04_LVL02 compute statistics ;
    So far so good. Now let's do an EXPLAIN using the exact
    same DDL used to create the MV:
    explain plan
    set STATEMENT_ID = 'FACT04'
    for
    select
    d04.DKEY
    , d04.LVL02_DESCR
    , f.KEY01
    , f.KEY03
    , f.YEAR_MONTH
    , f.SCENARIO
    , sum(f.AMOUNT) "AMOUNT"
    from FACT1 f
    , DIM04 d04
    where (f.KEY04 = d04.KEY04)
    and (f.ATTR01 = 'O')
    and (d04.LVL01_DESCR = '9999')
    and (f.SCENARIO IN ('ACT', 'PLAN'))
    group by
    d04.DKEY
    , d04.LVL02_DESCR
    , f.KEY01
    , f.KEY03
    , f.YEAR_MONTH
    , f.SCENARIO
    This gives:
    Query Plan
    SELECT STATEMENT Cost = 602
    TABLE ACCESS FULL FACT_DIM04_LVL02
    Great. However, now let's add one tiny little additional
    where clause to the query:
    explain plan
    set STATEMENT_ID = 'FACT04'
    for
    select /*+ REWRITE */
    d04.DKEY
    , d04.LVL02_DESCR
    , f.KEY01
    , f.KEY03
    , f.YEAR_MONTH
    , f.SCENARIO
    , sum(f.AMOUNT) "AMOUNT"
    from FACT1 f
    , DIM04 d04
    where (f.KEY04 = d04.KEY04)
    and (f.ATTR01 = 'O')
    and (d04.LVL01_DESCR = '9999')
    and (f.SCENARIO IN ('ACT', 'PLAN'))
    and (1 = 1)
    group by
    d04.DKEY
    , d04.LVL02_DESCR
    , f.KEY01
    , f.KEY03
    , f.YEAR_MONTH
    , f.SCENARIO
    Notice that I added the simplest predicate possible
    (1 = 1), AND I've added a hint telling the optimizer
    to use the new MV. However, Oracle does not recognize
    the MV; instead it goes back to the base tables:
    Query Plan
    SELECT STATEMENT Cost = 4130
    SORT GROUP BY
    HASH JOIN
    TABLE ACCESS BY INDEX ROWID DIM04
    INDEX RANGE SCAN DIM04_LVL02
    TABLE ACCESS FULL FACT_DIM04_LVL02
    In other words, this MV only seems to work if you're using
    the EXACT query that was used to create the MV, which
    makes it almost useless.
    I notice that in DBA_MVIEWS, there's a field called
    REWRITE_CAPABILITY, and this has a value of TEXTMATCH:
    SQLlist
    1 select mview_name, rewrite_enabled, rewrite_capability
    2* from dba_mviews
    SQL/
    MVIEW_NAME R REWRITE_C
    FACT_DIM04_LVL02 Y TEXTMATCH
    TEST01 Y GENERAL
    Here's what the manual says about this:
    TEXTMATCH: The defining query of the materialized view
    contained restrictions on the use of query rewrite.
    Yes, I'm using CBO and have set QUERY REWRITE to true.
    Also, should it matter, we're on 8.17, Sun Solaris 2.7
    Any ideas out there? TIA.

    What is the value of the job_queue_processes initialization parameter?
    Check dba|all|user_jobs to see if a refresh is actually scheduled and not marked broken.
    If a job is present, what is the value of the next_date column?

  • Should I use materialised view?

    I am using the following sql in my code. This takes a long time to execute and I need to tune this. Please review and suggest if I should be using a materialized view instead.
    Main Select statement for interest calculation
    SELECT          intratechgcur.SECURITY, intratechgcur.srl_no, intratechgcur.schg_type,
         CASE WHEN intratechgcur.effective_date < ADt_Start_Date THEN ADt_Start_Date
                             ELSE intratechgcur.effective_date END AS start_date,
         CASE WHEN intratechgcur.effective_date < ADt_End_Date
                             AND NVL(intratechgnext.effective_date, ADt_End_Date) > ADt_End_Date THEN ADt_End_Date
                             ELSE NVL(intratechgnext.effective_date, ADt_End_Date) END AS end_date,
                        intratechgcur.rate, intratechgcur.face_value, intratechgcur.listing_int, intratechgcur.comm_prod_int,
                        intratechgcur.sec_create_int, intratechgcur.int_type, intratechgcur.interest_key, intratechgcur.margin,
                        intratechgcur.FLOOR, intratechgcur.cap, intratechgcur.reset_freq, intratechgcur.cmpd_y_n, intratechgcur.cmpd_freq,
                        intratechgcur.comp_type, intratechgcur.int_day, intratechgcur.int_day_1, intratechgcur.int_day_2, intratechgcur.int_dtls_yn
    FROM               v_intratechg intratechgcur, v_intratechg intratechgnext
    WHERE               intratechgcur.SECURITY          = AS_Security
    AND          intratechgcur.effective_date < ADt_End_Date
    AND               intratechgnext.SECURITY          (+)= intratechgcur.SECURITY
    AND               intratechgnext.srl_no          (+)= intratechgcur.srl_no + 1
    ORDER BY      intratechgcur.SECURITY, intratechgcur.effective_date, intratechgcur.srl_no ;
    The code for the view V_intratechg is;
    CREATE OR REPLACE VIEW V_INTRATECHG AS
    SELECT     security,
         schg_type,
         effective_date,
         SUM(1) over (PARTITION BY security ORDER BY security, effective_date ASC, schg_type ASC) AS srl_no,
         face_value,
         rate,
         listing_int,
         comm_prod_int,
         sec_create_int,
         int_type,
         interest_key,
         margin,
         FLOOR,
         cap,
         NVL(reset_freq, 'DAILY') AS reset_freq,
         NVL(cmpd_y_n, 'N') AS cmpd_y_n,
         NVL(cmpd_freq, 'DAILY') AS cmpd_freq,
         NVL(comp_type, 'N') AS comp_type,
         int_day, int_day_1, int_day_2, int_dtls_yn
    FROM
         (SELECT     security.security, 'IM' AS schg_type,
              GREATEST(security.prv_int_dt, NVL(security.allot_date, security.prv_int_dt),
              NVL(security.first_int_date,security.prv_int_dt)) AS effective_date,
              DECODE(intday.int_day_1, 'ACD', NVL((SELECT interest_amt FROM securityschddtls A WHERE security.security = A.security
              AND A.adhoc_schd_date > GREATEST(security.prv_int_dt, NVL(security.allot_date, security.prv_int_dt),
              NVL(security.first_int_date,security.prv_int_dt))
              AND a.rectype ='L' AND A.ADHOC_SCHD_DATE = (SELECT MIN(ADHOC_SCHD_DATE) FROM securityschddtls
    WHERE      securityschddtls.adhoc_schd_date > GREATEST(security.prv_int_dt, NVL(security.allot_date, security.prv_int_dt), NVL(security.first_int_date,security.prv_int_dt))
         AND securityschddtls.security = A.security AND securityschddtls.rectype='L')),
              NVL(secchg.rate, security.interest)), NVL(secchg.rate, security.interest)) AS rate,
              NVL(secchg.face_value, security.face_value) AS face_value,
              NVL(secchg.listing_int, security.listing_int) AS listing_int,
              NVL(secchg.comm_prod_int, security.comm_prod_int) AS comm_prod_int,
              NVL(secchg.sec_create_int,security.sec_create_int) AS sec_create_int,
              NVL(secchg.int_type, security.int_type) AS int_type,
              NVL(secchg.interest_key, security.interest_key) AS interest_key,
              NVL(secchg.margin, security.margin) AS margin,
              NVL(secchg.FLOOR, security.FLOOR) AS FLOOR,
              NVL(secchg.cap, security.cap) AS cap,
              NVL(secchg.reset_freq, security.reset_freq) AS reset_freq,
              NVL(secchg.cmpd_y_n, security.cmpd_y_n) AS cmpd_y_n,
              NVL(secchg.cmpd_freq, security.cmpd_freq) AS cmpd_freq,
              NVL(secchg.comp_type, security.comp_type) AS comp_type,
              NVL(secchg.int_day, security.int_day) AS int_day, intday.int_day_1,
              intday.int_day_2, 'Y' AS int_dtls_yn
              FROM          security, assetype, intday, securityschddtls secdtls,
                        (SELECT     secchg.security AS security, secchg.call_date AS effective_date,
                        NVL(secchg.rate,0) AS rate, secchg.face_value,
                        SUM(1) over (PARTITION BY secchg.security ORDER BY secchg.security,
                        secchg.call_date ASC) AS srl_no,
                        NVL(secchg.listing_int,0) AS listing_int, NVL(secchg.comm_prod_int,0) AS comm_prod_int,
                        NVL(secchg.sec_create_int,0) AS sec_create_int,
                        secchg.int_type, secchg.interest_key,
                        nvl(secchg.margin,0) as margin, nvl(secchg.FLOOR,0) as floor,
                        nvl(secchg.cap,0) as cap, secchg.reset_freq,
                        secchg.cmpd_y_n, secchg.cmpd_freq, secchg.comp_type, secchg.int_day FROM          secchg) secchg
              WHERE          security.asset_type     = assetype.asset_type
                   AND          security.int_day          = intday.int_day
                   AND          assetype.int_y_n           = 'Y'
                   AND          security.rectype          = 'L'
                   AND          assetype.rectype          = 'L'
                   AND          intday.rectype               = 'L'
                   AND          secchg.security (+)= security.security
                        AND          secchg.srl_no (+)= 1
                        AND          secdtls.security (+)= security.security
                        AND          secdtls.srl_no (+)= 1
                        AND          secdtls.rectype (+)= 'L'
              UNION ALL
              SELECT     schedules.security,
                   DECODE(schedules.schd_past_yn, 'Y', 'RP', 'RS') AS schg_type,
                   DECODE(intday.int_day_1, 'ACD',security_cashflow.start_date,security_cashflow.inflow_date) AS effective_date,
                   --commented by vijai
                   -- DECODE(intday.int_day_1, 'ACD', intschdamt.amount, NVL(intratechg.rate,security.interest)) AS rate,
                   DECODE(intday.int_day_1, 'ACD', intschdamt.amount,decode(security_cashflow.start_Date,intratechg.value_Date, intratechg.rate, security.interest)) as rate,
                   decode(nvl(schedules.tot_face_value - schedules.cum_face_value,security.face_value),0,security.face_value,schedules.tot_face_value - schedules.cum_face_value,security.face_value) AS face_value,
                   NVL(intratechg.listing_int,security.listing_int) as listing_int,
                   NVL(intratechg.comm_prod_int,security.comm_prod_int) as comm_prod_int,
                   NVL(intratechg.sec_create_int,security.sec_create_int),
                   NVL(intratechg.int_type,security.int_type) as int_type,
                   nvl(intratechg.interest_key,security.interest_key) as interest_key,
                   nvl(intratechg.margin,security.margin) as margin,
                   nvl(intratechg.FLOOR,security.floor) as floor,
                   nvl(intratechg.cap,security.cap) as cap,
                   nvl(intratechg.reset_freq,security.reset_freq) as reset_freq,
                   nvl(intratechg.cmpd_y_n,security.cmpd_y_n) as cmpd_y_n,
                   nvl(intratechg.cmpd_freq,security.cmpd_freq) as cmpd_freq,
                   nvl(intratechg.comp_type,security.comp_type),
                   nvl(intratechg.int_day,security.int_day),
                   intday.int_day_1, intday.int_day_2,
                   DECODE(intratechg.security, NULL, 'N', 'Y') AS int_dtls_yn
              FROM     v_schedules schedules, security, intday, intratechg, v_schedules intschdamt, security_cashflow
              WHERE     schedules.security          = security.security
              AND          schedules.red_yn      = 'Y'
              AND          security.int_day               = intday.int_day
              AND          security.rectype               = 'L'
              AND          intday.rectype                    = 'L'
              AND          intratechg.security (+)= schedules.security
              AND          intratechg.value_date(+)= schedules.schd_date
              AND          intratechg.rectype     (+)= 'L'
              AND          intschdamt.security (+)= schedules.security
              AND          intschdamt.schd_date (+)= schedules.schd_date
              AND          intschdamt.red_yn (+)= 'N'
              AND           security_cashflow.inflow_type      = 'INT'
              AND           security_cashflow.inflow_date     = schedules.schd_date
              AND           security.security               = security_cashflow.security
              AND           schedules.security          = security_cashflow.security
              UNION ALL
              SELECT     intratechg.security, 'IR' AS schg_type,
                   intratechg.value_date AS effective_date,
                   NVL(intratechg.rate,security.interest),
                   security.face_value,
                   NVL(intratechg.listing_int,security.listing_int),
                   NVL(intratechg.comm_prod_int,security.comm_prod_int),
                   NVL(intratechg.sec_create_int,security.sec_create_int),
                   nvl(intratechg.int_type,security.int_type),
                   nvl(intratechg.interest_key,security.interest_key),
                   nvl(intratechg.margin,security.margin),
                   nvl(intratechg.FLOOR,security.floor),
                   nvl(intratechg.cap,security.cap),
                   nvl(intratechg.reset_freq,security.reset_freq),
                   nvl(intratechg.cmpd_y_n,security.cmpd_y_n),
                   nvl(intratechg.cmpd_freq,security.cmpd_freq),
                   nvl(intratechg.comp_type,security.comp_type),
                   nvl(intratechg.int_day,security.int_day),
                   intday.int_day_1, intday.int_day_2, 'Y' AS int_dtls_yn
              FROM     intratechg, security, intday
              WHERE     intratechg.security          = security.security
              AND     security.int_day               = intday.int_day
              AND     intratechg.rectype          = 'L'
              AND     security.rectype               = 'L'
              AND     intday.rectype                    = 'L'
              AND     NOT EXISTS     (SELECT     1 FROM          v_schedules schedules
                             WHERE          schedules.security     = intratechg.security
                             AND          schedules.schd_date     = intratechg.value_date
                             AND          schedules.red_yn          = 'Y'))
              ORDER BY security, srl_no
    The code for the view V_schedules is;
    CREATE OR REPLACE VIEW V_SCHEDULES AS
    SELECT schdall.security,
              schdall.schd_date,
              schdall.schd_type,
              schdall.percent,
              schdall.units_o,
              schdall.units_n,
              schdall.amount,
              schdall.sequences,
    schdall.act_sch_dt,
         schdall.security_n,
              schdall.prior_act,
         schdall.red_amount,
              schdall.ben_refer,
         schdall.round_method,
    schdall.round_dec,
    schdall.average_y_n,
         schdall.schd_past_yn,
         CASE WHEN schd_type IN(sysschd.red, sysschd.disred) THEN 'Y' ELSE 'N' END AS red_yn,
         SUM( CASE WHEN schd_type IN(sysschd.red, sysschd.disred) THEN schdall.red_amount ELSE 0 END)
                                  over(PARTITION BY schdall.security) AS tot_face_value,
    SUM( CASE WHEN schd_type IN(sysschd.red, sysschd.disred) THEN schdall.red_amount ELSE 0 END)
                                  over(PARTITION BY schdall.security
                                       ORDER BY schdall.security, schdall.schd_date ASC) AS cum_face_value,
         SUM( CASE WHEN schd_type IN(sysschd.red, sysschd.disred) THEN schdall.red_amount ELSE 0 END)
                                       over(PARTITION BY schdall.security
                                       ORDER BY schdall.security, schdall.schd_date DESC) AS to_be_redeemed ,
              SUM(CASE WHEN schd_type =sysschd.INT THEN 0 ELSE 1 END)
                                       over(PARTITION BY schdall.security,schdall.schd_date,schd_type)
                             AS no_of_schd
    FROM
                   (SELECT      schedules.security_o AS security,
                                  schedules.schd_date,
                                  schedules.schd_type,
                                  schedules.percent,
                                  schedules.units_o,
                                  schedules.units_n,
                                  schedules.amount,
                                  schedules.sequences,
                                  schedules.act_sch_dt,
                                  schedules.security_n,
                                  schedules.prior_act,
                                  schedules.red_amount,
                                  schedules.ben_refer,
                                  schedules.round_method,
                                  schedules.round_dec,
                                  schedules.average_y_n,
                                  DECODE(schedules.schd_type,'RED','Y','Y') AS schd_past_yn
              FROM           schdpast schedules
              WHERE           prior_act = 'A'
              AND                rectype = 'L'
              UNION ALL
              SELECT           schedules.security_o AS security,
                                  schedules.schd_date,
                                  schedules.schd_type,
                                  schedules.percent,
                             schedules.units_o,
                   schedules.units_n,
                             schedules.amount,
                        schedules.sequences,
                        schedules.act_sch_dt,
                   schedules.security_n,
                   schedules.prior_act,
                        schedules.red_amount,
                        schedules.ben_refer,
                   schedules.round_method,
                   schedules.round_dec,
                   schedules.average_y_n,
                        'N' AS schd_past_yn
              FROM           schedules
              WHERE           prior_act = 'A'
              AND                rectype = 'L'
              AND                Process_date IS NULL ) schdall,
              (SELECT           MAX(redschdtype) AS red,
                             MAX(disredtype) AS disred,
                                  MAX(intschdtype) AS      INT
                                  FROM sysparamschd
              WHERE rectype = 'L') sysschd
    ORDER BY security, schd_date, schd_type

    Too much SQL... makes me eyes hurt.
    I think you're running down the wrong alley here. The very first and fundamental principle of performance tuning is identifying the performance problem. Saying that there is a problem is not identifying the actual problem.
    You cannot run down the alley with a knife looking for a performance problem to kill if you do not know how it looks like. Good that you are running though - the old Klingon saying of "a running warrior can slit more throats" hold very true. :-)
    Why is the existing SQL slow? You first need to identify that. Sure, a materialised view can make the end-query much faster as it has no longer to do all the work - that has now been done in batch by a DBMS_REFRESH job updating and maintaining that materialised view. But that work is still done... so have you actually fixed the cause of the performance problem, or merely hid it by addressing the symptoms?
    How does one find and identify the underlaying performance problem with too-much-SQL-that-makes-Billy's-eyes-hurt? Software Engineering 101. Take any complex problem. Break it down into lots of smaller little problems. Solve each on in turn.
    Take the SQL, break it down into simpler pieces and check each for performance issues. Look at the execution plan and cost. Determime if you (via the physical db design) are providing optimal I/O paths to the CBO in order for it to get to the required data with as little I/O as possible.
    Once you deal with the facts, you can make an informed decision or whether or not a materialised view will actually fix the cause of the performance problem.

  • 10g query running faster with RBO than CBO

    I am running a query in Oracle 10g that is taking 1minute 15 seconds to run using the CBO. All the tables and indexes in the query are fully analyzed. However if i add a /*+ Rule */ hint to the query and force the optimizer to RBO it runs in 5 seconds.
    Anyone any ideas why this would occur? it's contrary to everything Oracle says about CBO and problematic as RBO is no longer supported in 10g
    Any help / advice greatfully appreciated
    Thanks
    Declan

    My "best" CBO explain plan is......
    Explain complete.
    Elapsed: 00:00:01:90
    PLAN_TABLE_OUTPUT                                                                                                                           
    | Id  | Operation                          |  Name                          | Rows  | Bytes |TempSpc| Cost  |                               
    |   0 | SELECT STATEMENT                   |                                |  3364K|  2553M|       |   666K|                               
    |   1 |  SORT ORDER BY                     |                                |  3364K|  2553M|  5840M|   666K|                               
    |   2 |   VIEW                             |                                |  3364K|  2553M|       |   273K|                               
    |   3 |    UNION-ALL                       |                                |       |       |       |       |                               
    |*  4 |     HASH JOIN                      |                                |  2269K|  1415M|       |   255K|                               
    |*  5 |      TABLE ACCESS FULL             | NODE                           |     6 |   198 |       |   183 |                               
    |*  6 |      HASH JOIN OUTER               |                                |  2269K|  1344M|       |   255K|                               
    |*  7 |       HASH JOIN                    |                                |   710 |   266K|       |  2179 |                               
    |*  8 |        HASH JOIN OUTER             |                                |  1219 |   165K|       |   355 |                               
    |*  9 |         HASH JOIN                  |                                |  1219 |   154K|       |   318 |                               
    |* 10 |          HASH JOIN                 |                                |  1219 |   138K|       |   260 |                               
    |* 11 |           HASH JOIN                |                                |  1219 |   127K|       |   224 |                               
    |  12 |            TABLE ACCESS FULL       | TMP_NODE_WALK_ALL_NODES        |  8168 |   311K|       |    17 |                               
    |* 13 |            HASH JOIN               |                                | 10896 |   723K|       |   201 |                               
    |  14 |             INDEX FAST FULL SCAN   | PK_NODE_RULES_NODE_ID_RULE_ID  | 10896 |   106K|       |     6 |                               
    |  15 |             TABLE ACCESS FULL      | NODE                           | 73004 |  4134K|       |   183 |                               
    |  16 |           INDEX FAST FULL SCAN     | IDX_NODE_CIX2                  | 73004 |   641K|       |    33 |                               
    PLAN_TABLE_OUTPUT                                                                                                                           
    |  17 |          INDEX FAST FULL SCAN      | IDX_NODE_CIX1                  | 73004 |   998K|       |    54 |                               
    |  18 |         INDEX FAST FULL SCAN       | IDX_NODE_CIX2                  | 73004 |   641K|       |    33 |                               
    |* 19 |        TABLE ACCESS FULL           | RULES                          |  6344 |  1517K|       |  1820 |                               
    |  20 |       VIEW                         |                                |   405M|    89G|       | 43581 |                               
    |* 21 |        HASH JOIN OUTER             |                                |   405M|    23G|       | 43581 |                               
    |  22 |         TABLE ACCESS FULL          | TMP_NODE_WALK_ALL_NODES        |  8168 |   103K|       |    17 |                               
    |  23 |         TABLE ACCESS FULL          | UNIVERSAL_RULES                |  3377K|   157M|       | 43256 |                               
    |* 24 |     HASH JOIN OUTER                |                                |  1094K|   410M|   148M| 17453 |                               
    |  25 |      MERGE JOIN CARTESIAN          |                                |   390K|   143M|       | 15029 |                               
    |  26 |       NESTED LOOPS                 |                                |    70 | 25060 |       |  2849 |                               
    |  27 |        NESTED LOOPS                |                                |    70 | 21000 |       |  2779 |                               
    |  28 |         TABLE ACCESS BY INDEX ROWID| UNIVERSAL_RULES                |  1392 | 76560 |       |  1387 |                               
    |* 29 |          INDEX RANGE SCAN          | IDX_UNIVERSAL_RULES_ACCOUNT    |  1392 |       |       |     6 |                               
    |* 30 |         TABLE ACCESS BY INDEX ROWID| RULES                          |     1 |   245 |       |     1 |                               
    |* 31 |          INDEX UNIQUE SCAN         | PK_RULES_RULE_ID_VERSION_ID    |    20 |       |       |       |                               
    |* 32 |        TABLE ACCESS BY INDEX ROWID | NODE                           |     1 |    58 |       |     1 |                               
    |* 33 |         INDEX UNIQUE SCAN          | PK_NODE_NODE_ID                |     6 |       |       |       |                               
    |  34 |       BUFFER SORT                  |                                |  5616 |   153K|       | 15028 |                               
    |  35 |        TABLE ACCESS BY INDEX ROWID | NODE                           |  5616 |   153K|       |   174 |                               
    |* 36 |         INDEX RANGE SCAN           | IDX_NODE_NODE_TYPE_ID          |  5616 |       |       |    11 |                               
    |* 37 |      INDEX FAST FULL SCAN          | IDX_RULES_RULE_ID_STATUS       | 42293 |   289K|       |    48 |                               
    PLAN_TABLE_OUTPUT                                                                                                                           
    Predicate Information (identified by operation id):                                                                                         
       4 - access("NODE"."NODE_TYPE_ID"="SN"."HIERARCHY_TYPE_ID")                                                                               
       5 - filter("NODE"."PARENT_NODE_ID" IS NULL)                                                                                              
       6 - access("SYS_ALIAS_1"."RULE_ID"="UR"."RULE_ID"(+) AND "SYS_ALIAS_1"."VERSION_ID"="UR"."VERSION_ID"(+))                                
       7 - access("NR"."RULE_ID"="SYS_ALIAS_1"."COMBINED_RULE_ID")                                                                              
       8 - access("SN"."PARENT_NODE_ID"="SP"."NODE_ID"(+))                                                                                      
       9 - access("AN"."START_NODE_ID"="SN"."NODE_ID")                                                                                          
      10 - access("AN"."EFFECTIVE_NODE_ID"="EN"."NODE_ID")                                                                                      
      11 - access("AN"."SHORTCUT_NODE_ID"="N"."NODE_ID")                                                                                        
      13 - access("N"."NODE_ID"="NR"."NODE_ID")                                                                                                 
      19 - filter(',A,P,' LIKE '%,'||"SYS_ALIAS_1"."STATUS"||',%')                                                                              
      21 - access("UR"."NODE_ID"(+)="AN"."START_NODE_ID")                                                                                       
      24 - access("R"."RULE_ID"="RP"."RULE_ID"(+))                                                                                              
      29 - access("UR"."ACCOUNT_ID"='0069')                                                                                                     
      30 - filter(',A,P,' LIKE '%,'||"R"."STATUS"||',%')                                                                                        
      31 - access("UR"."RULE_ID"="R"."RULE_ID" AND "UR"."VERSION_ID"="R"."VERSION_ID")                                                          
      32 - filter("N"."HIERARCHY_TYPE_ID"=9)                                                                                                    
    PLAN_TABLE_OUTPUT                                                                                                                           
      33 - access("UR"."NODE_ID"="N"."NODE_ID")                                                                                                 
      36 - access("NODE"."NODE_TYPE_ID"=9)                                                                                                      
      37 - filter("RP"."STATUS"(+)='P')                                                                                                         
    Note: cpu costing is off                                                                                                                    
    28 rows selected.
    Elapsed: 00:00:02:45
    68 rows selected.
    Elapsed: 00:00:05:76While my RBO explain plan is
    Explain complete.
    Elapsed: 00:00:01:23
    PLAN_TABLE_OUTPUT                                                                                                                           
    | Id  | Operation                                |  Name                        | Rows  | Bytes | Cost  |                                   
    |   0 | SELECT STATEMENT                         |                              |       |       |       |                                   
    |   1 |  SORT ORDER BY                           |                              |       |       |       |                                   
    |   2 |   VIEW                                   |                              |       |       |       |                                   
    |   3 |    UNION-ALL                             |                              |       |       |       |                                   
    |   4 |     MERGE JOIN OUTER                     |                              |       |       |       |                                   
    |   5 |      SORT JOIN                           |                              |       |       |       |                                   
    |*  6 |       TABLE ACCESS BY INDEX ROWID        | NODE                         |       |       |       |                                   
    |   7 |        NESTED LOOPS                      |                              |       |       |       |                                   
    |   8 |         NESTED LOOPS                     |                              |       |       |       |                                   
    |   9 |          NESTED LOOPS                    |                              |       |       |       |                                   
    |  10 |           NESTED LOOPS                   |                              |       |       |       |                                   
    |  11 |            NESTED LOOPS                  |                              |       |       |       |                                   
    |  12 |             NESTED LOOPS OUTER           |                              |       |       |       |                                   
    |  13 |              NESTED LOOPS                |                              |       |       |       |                                   
    |  14 |               TABLE ACCESS FULL          | TMP_NODE_WALK_ALL_NODES      |       |       |       |                                   
    |  15 |               TABLE ACCESS BY INDEX ROWID| NODE                         |       |       |       |                                   
    |* 16 |                INDEX UNIQUE SCAN         | PK_NODE_NODE_ID              |       |       |       |                                   
    PLAN_TABLE_OUTPUT                                                                                                                           
    |  17 |              TABLE ACCESS BY INDEX ROWID | NODE                         |       |       |       |                                   
    |* 18 |               INDEX UNIQUE SCAN          | PK_NODE_NODE_ID              |       |       |       |                                   
    |  19 |             TABLE ACCESS BY INDEX ROWID  | NODE                         |       |       |       |                                   
    |* 20 |              INDEX UNIQUE SCAN           | PK_NODE_NODE_ID              |       |       |       |                                   
    |  21 |            TABLE ACCESS BY INDEX ROWID   | NODE                         |       |       |       |                                   
    |* 22 |             INDEX UNIQUE SCAN            | PK_NODE_NODE_ID              |       |       |       |                                   
    |  23 |           TABLE ACCESS BY INDEX ROWID    | NODE_RULES                   |       |       |       |                                   
    |* 24 |            INDEX RANGE SCAN              | IDX_NODE_RULES_NODE_ID       |       |       |       |                                   
    |* 25 |          TABLE ACCESS BY INDEX ROWID     | RULES                        |       |       |       |                                   
    |* 26 |           INDEX RANGE SCAN               | IDX_RULES_COMBINED_RULE_ID   |       |       |       |                                   
    |* 27 |         INDEX RANGE SCAN                 | IDX_NODE_NODE_TYPE_ID        |       |       |       |                                   
    |* 28 |      SORT JOIN                           |                              |       |       |       |                                   
    |  29 |       VIEW                               |                              |       |       |       |                                   
    |  30 |        NESTED LOOPS OUTER                |                              |       |       |       |                                   
    |  31 |         TABLE ACCESS FULL                | TMP_NODE_WALK_ALL_NODES      |       |       |       |                                   
    |  32 |         TABLE ACCESS BY INDEX ROWID      | UNIVERSAL_RULES              |       |       |       |                                   
    |* 33 |          INDEX RANGE SCAN                | IDX_UNIVERSAL_RULES_NODE     |       |       |       |                                   
    |  34 |     NESTED LOOPS OUTER                   |                              |       |       |       |                                   
    |  35 |      NESTED LOOPS                        |                              |       |       |       |                                   
    |  36 |       NESTED LOOPS                       |                              |       |       |       |                                   
    |  37 |        NESTED LOOPS                      |                              |       |       |       |                                   
    PLAN_TABLE_OUTPUT                                                                                                                           
    |  38 |         TABLE ACCESS BY INDEX ROWID      | NODE                         |       |       |       |                                   
    |* 39 |          INDEX RANGE SCAN                | IDX_NODE_NODE_TYPE_ID        |       |       |       |                                   
    |  40 |         TABLE ACCESS BY INDEX ROWID      | UNIVERSAL_RULES              |       |       |       |                                   
    |* 41 |          INDEX RANGE SCAN                | IDX_UNIVERSAL_RULES_ACCOUNT  |       |       |       |                                   
    |* 42 |        TABLE ACCESS BY INDEX ROWID       | NODE                         |       |       |       |                                   
    |* 43 |         INDEX UNIQUE SCAN                | PK_NODE_NODE_ID              |       |       |       |                                   
    |* 44 |       TABLE ACCESS BY INDEX ROWID        | RULES                        |       |       |       |                                   
    |* 45 |        INDEX UNIQUE SCAN                 | PK_RULES_RULE_ID_VERSION_ID  |       |       |       |                                   
    |* 46 |      INDEX RANGE SCAN                    | IDX_RULES_RULE_ID_STATUS     |       |       |       |                                   
    Predicate Information (identified by operation id):                                                                                         
       6 - filter("NODE"."PARENT_NODE_ID" IS NULL)                                                                                              
      16 - access("AN"."START_NODE_ID"="SN"."NODE_ID")                                                                                          
      18 - access("SN"."PARENT_NODE_ID"="SP"."NODE_ID"(+))                                                                                      
      20 - access("AN"."EFFECTIVE_NODE_ID"="EN"."NODE_ID")                                                                                      
      22 - access("AN"."SHORTCUT_NODE_ID"="N"."NODE_ID")                                                                                        
      24 - access("N"."NODE_ID"="NR"."NODE_ID")                                                                                                 
      25 - filter(',A,P,' LIKE '%,'||"SYS_ALIAS_1"."STATUS"||',%')                                                                              
    PLAN_TABLE_OUTPUT                                                                                                                           
      26 - access("NR"."RULE_ID"="SYS_ALIAS_1"."COMBINED_RULE_ID")                                                                              
      27 - access("NODE"."NODE_TYPE_ID"="SN"."HIERARCHY_TYPE_ID")                                                                               
      28 - access("SYS_ALIAS_1"."RULE_ID"="UR"."RULE_ID"(+))                                                                                    
           filter("SYS_ALIAS_1"."VERSION_ID"="UR"."VERSION_ID"(+) AND                                                                           
                  "SYS_ALIAS_1"."RULE_ID"="UR"."RULE_ID"(+))                                                                                    
      33 - access("UR"."NODE_ID"(+)="AN"."START_NODE_ID")                                                                                       
      39 - access("NODE"."NODE_TYPE_ID"=9)                                                                                                      
      41 - access("UR"."ACCOUNT_ID"='0069')                                                                                                     
      42 - filter("N"."HIERARCHY_TYPE_ID"=9)                                                                                                    
      43 - access("UR"."NODE_ID"="N"."NODE_ID")                                                                                                 
      44 - filter(',A,P,' LIKE '%,'||"R"."STATUS"||',%')                                                                                        
      45 - access("UR"."RULE_ID"="R"."RULE_ID" AND "UR"."VERSION_ID"="R"."VERSION_ID")                                                          
      46 - access("R"."RULE_ID"="RP"."RULE_ID"(+) AND "RP"."STATUS"(+)='P')                                                                     
    Note: rule based optimization                                                                                                               
    28 rows selected.
    Elapsed: 00:00:04:42
    78 rows selected.
    Elapsed: 00:00:08:86Any additional help appreciated
    I am going to try and run a trace against the sql now and see if i can get any more information
    Thanks in advance
    Declan

Maybe you are looking for