Table Access Path

Hi,
I am using oracle 10g on windowz xp. I am giving below query :
SQL> ED
Wrote file afiedt.buf
  1  SELECT GRANTEE,PRIVILEGE,GRANTABLE FROM DBA_TAB_PRIVS
  2  WHERE
  3  OWNER='SCOTT' AND
  4* TABLE_NAME='EMP'
SQL> /
GRANTEE                        PRIVILEGE                                GRA
HR                             SELECT                                   YES
TEST                           SELECT                                   NO
TESTROLE                       SELECT                                   NO
TESTROLE                       UPDATE                                   NO
SQL>But i need output in below manner :
GRANTEE                        PRIVILEGE                                GRA
HR (DIRECT)                    SELECT                                   YES
TEST (DIRECT)                  SELECT                                   NO
TEST (THROUGH-->TESTROLE)      SELECT                                   NO
ABC (THROUGH-->TESTROLE)       UPDATE                                   NOI mean how do i know that which user is having which privilege on scott.emp through direct access or through a role. If user is having direct privilege it should be (USERNAME (DIRECT)) in GRANTEE column else (USERNAME (THROUGH-->ROLENAME).
Thanks in advance.

Hello Anuragji,
Yes, your query is taking care of it, but i have a little question (basic) :
SQL> select t.grantee, null Through, t.privilege, t.grantable
  2       from dba_tab_privs t
  3       where t.grantee in (select username from dba_users) and owner = 'SCOTT' and table_name = 'EMP'
  4  union all
  5  select r.grantee, tr.grantee Through, tr.privilege, tr.grantable
  6       from dba_tab_privs tr, dba_role_privs r
  7       where r.granted_role=tr.grantee and owner = 'SCOTT' and table_name = 'EMP';
GRANTEE                        THROUGH                        PRIVILEGE                                GRA
HR                                                            SELECT                                   YES
TEST                                                          SELECT                                   NO
SYS                            TESTROLE                       SELECT                                   NO
HR                             TESTROLE                       SELECT                                   NO
SYS                            TESTROLE                       UPDATE                                   NO
HR                             TESTROLE                       UPDATE                                   NO
6 rows selected.
SQL> show user;
USER is "SYS"
SQL> delete from scott.emp;
15 rows deleted.
SQL> rollback;
Rollback complete.My question is if sys is not having delete privilege on scott.emp as output shown above, then how 15 rows deleted?
Thank you again for your replies.

Similar Messages

  • How improve performance on access path TABLE ACCESS BY INDEX ROWID ?

    I have table MOVEMENT with about 26millions entries,
    select rowid from movement xxx
    where
    xxx.sTransType > 0
    AND xxx.sDevice < 1000
    AND xxx.sDevice >= 0
    AND (bitand(xxx.sSaleFlag,1) = 0 AND bitand(xxx.sSaleFlag,4) = 0)
    AND xxx.sArtClassRef < 100
    and xxx.tActionTime BETWEEN TO_DATE('13-05-2011 08:08:34', 'dd-mm-yyyy hh24:mi:ss') AND to_date('13-05-2011 14:08:34', 'dd-mm-yyyy hh24:mi:ss') ;
    PLAN_TABLE_OUTPUT
    Plan hash value: 679628763
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 1 | 34 | 10102 (1)| 00:02:02 |
    |* 1 | TABLE ACCESS BY INDEX ROWID| MOVEMENT | 1 | 34 | 10102 (1)| 00:02:02 |
    |* 2 | INDEX RANGE SCAN | MOVATIME_IX | 18489 | | 51 (0)| 00:00:01 |
    Predicate Information (identified by operation id):
    1 - filter("XXX"."SARTCLASSREF"<100 AND BITAND("XXX"."SSALEFLAG",1)=0 AND
    BITAND("XXX"."SSALEFLAG",4)=0 AND "XXX"."STRANSTYPE">0 AND "XXX"."SDEVICE"<1000
    AND "XXX"."SDEVICE">=0)
    2 - access("XXX"."TACTIONTIME">=TO_DATE('2011-05-13 08:08:34', 'yyyy-mm-dd
    hh24:mi:ss') AND "XXX"."TACTIONTIME"<=TO_DATE('2011-05-13 14:08:34', 'yyyy-mm-dd
    hh24:mi:ss'))
    there is index on tActionTime - MOVATIME_IX
    This query returns 12203 rows, so I would anticipate this number in plan table in row with id 1 and column Rows
    Final question if it is possible to optimize this query and what are the next steps to do it?
    Thanks.

    >
    I thought that access path via ROWID's is the fastest way to get row
    >
    It is the fastest way to get the row - FROM THE TABLE.
    But the ROWIDs have to be gotten from the index. That is what the INDEX RANGE SCAN is doing. It is getting the ROWIDs needed and then the TABLE ACCESS BY INDEX ROWID is getting the rows.
    >
    I'am still confused with COST values, TABLE ACCESS BY INDEX ROWID has 200times higher cost than INDEX RANGE SCAN,
    >
    The index entries for a range scan are in order so they are very compact. The actual rows might be all over the place.
    Have you ever you a library? Not the online ones - I mean the old-fashioned kind that actually has books printed on paper?
    If the librarian asks you, her helper, to go get all books whose title begins with the letter 'B' how would you do it?
    You could go back to the stacks and look at every book on every shelf for books with titles' starting with 'B'. That is the same as a FULL TABLE SCAN.
    Or you could go to the card catalog, pull out the drawer (or drawers) that has 'B' on the label and look at the information on the card. Part of that information is the location of the actual book: section, stack; that is similar to the ROWID.
    The card catalog might get you to the right stack of books; then you have to search the stack sequentially to look for the book by name.
    A ROWID will get Oracle to the right block but then it has to find the right row.
    So the cost of getting ROWIDs from an index using a RANGE SCAN (where values are scanned in order) is a lot cheaper than actually getting the rows. The first two index entries needed might be right next to each other in order but the rows themselves might be far apart on the disk.

  • Index not being used in access path

    Hi,
    I have been trying to rewrite a query which currently is taking almost 1min and 25 secs to execute. The database version is 11.1.0.7.
    The query is -
    SELECT COUNT(1)
    FROM TAB1 p
    WHERE p.ACODE = 24377
    AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AKey )
    AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AKey )
    AND p.rflag = 'Y';
    The table originally didn't have an index on p.ACODE. So, I created this index and set it to visible and set the optimizer_use_invisible_indexes parameter also to TRUE. I set the monitoring on this index too. Even though I have created the index on the ACODE column, the access path doesn't use it. Can someone please tell me why this is not being used.
    Below is the explain plan for the sql stmt and the usage of the index -
    I have changed the actual table and column names -
    SQL> SELECT COUNT(1)
    2 FROM TAB1 p
    3 WHERE p.ACODE = 24377
    4 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AKey )
    5 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AKey )
    6 AND p.rflag = 'Y';
    COUNT(1)
    1
    SQL> explain plan for
    2 SELECT COUNT(1)
    3 FROM TAB1 p
    4 WHERE p.ACODE = 24377
    5 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AKey )
    6 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AKey )
    7 AND p.rflag = 'Y';
    Explained.
    Elapsed: 00:00:00.02
    SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql
    PLAN_TABLE_OUTPUT
    Plan hash value: 3942424611
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 1 | 87 | 214K (2)| 00:42:57 |
    | 1 | SORT AGGREGATE | | 1 | 87 | | |
    |* 2 | HASH JOIN ANTI | | 1 | 87 | 214K (2)| 00:42:57 |
    |* 3 | HASH JOIN ANTI | | 1 | 60 | 209K (2)| 00:41:56 |
    |* 4 | TABLE ACCESS FULL | TAB1 | 1 | 32 | 209K (2)| 00:41:55 |
    | 5 | INDEX FAST FULL SCAN| PK_TAB3 | 29918 | 818K| 53 (0)| 00:00:01 |
    | 6 | INDEX FAST FULL SCAN | PK_TAB2 | 3199K| 82M| 5059 (1)| 00:01:01 |
    Predicate Information (identified by operation id):
    2 - access("PH"."PKey"="P"."AKey")
    3 - access("PHS"."PKey"="P"."AKey")
    4 - filter(TO_NUMBER("P"."ACODE")=24377 AND "P"."rflag"='Y')
    20 rows selected.
    Elapsed: 00:00:00.03
    SQL> select index_name,VISIBILITY from user_indexes where index_name='IDX_TAB1_ACODE';
    INDEX_NAME VISIBILIT
    IDX_TAB1_ACODE VISIBLE
    Elapsed: 00:00:00.01
    SQL> show parameter visible
    NAME TYPE VALUE
    optimizer_use_invisible_indexes boolean TRUE
    SQL>
    SQL> SELECT v.index_name, v.table_name,
    v.monitoring, v.used,
    start_monitoring, end_monitoring
    FROM v$object_usage v, dba_indexes u
    WHERE v.index_name = u.index_name
    AND v.index_name = 'IDX_TAB1_ACODE';
    INDEX_NAME TABLE_NAME MON USE START_MONITORING END_MONITORING
    IDX_TAB1_ACODE TAB1 YES NO 05/26/2010 14:13:41
    Elapsed: 00:00:00.10
    Edited by: user12158503 on May 26, 2010 1:24 PM

    Thanks Centinul.
    I apologize for posting in both sections. I put it in the Database General too because I thought I originally posted it in the wrong section.
    The index was not being used because it was doing the implicit type conversion. When I enclosed it in quotes, it returns the result within a second and it uses the index.(whereas without the index it takes around 1min 25 sec)
    Here is the explain plan and execution time after enclosing it in quotes -
    SQL> explain plan for
    2 SELECT COUNT(1)
    3 FROM TAB1 p
    4 WHERE p.AKey = '24377'
    5 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AgilityKey )
    6 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AgilityKey )
    7 AND p.rflag = 'Y';
    Explained.
    Elapsed: 00:00:00.02
    SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql
    PLAN_TABLE_OUTPUT
    Plan hash value: 2008452282
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 1 | 87 | 5134 (1)| 00:01:02 |
    | 1 | SORT AGGREGATE | | 1 | 87 | | |
    |* 2 | HASH JOIN ANTI | | 1 | 87 | 5134 (1)| 00:01:02 |
    |* 3 | HASH JOIN ANTI | | 1 | 60 | 60 (2)| 00:00:01 |
    |* 4 | TABLE ACCESS BY INDEX ROWID| TAB1 | 1 | 32 | 6 (0)| 00:00:01 |
    |* 5 | INDEX RANGE SCAN | IDX_TAB1_AKey | 4 | | 1 (0)| 00:00:01 |
    | 6 | INDEX FAST FULL SCAN | PK_TAB3 | 29918 | 818K| 53 (0)| 00:00:01 |
    | 7 | INDEX FAST FULL SCAN | PK_TAB2 | 3199K| 82M| 5059 (1)| 00:01:01 |
    Predicate Information (identified by operation id):
    2 - access("PH"."PKey"="P"."AGILITYKEY")
    3 - access("PHS"."PKey"="P"."AGILITYKEY")
    4 - filter("P"."rflag"='Y')
    5 - access("P"."AKey"='24377')
    22 rows selected.
    Elapsed: 00:00:00.02
    SQL> SELECT COUNT(1)
    2 FROM TAB1 p
    3 WHERE p.AKey = '24377'
    4 AND NOT EXISTS (SELECT 1 FROM TAB2 ph where ph.PKey = p.AgilityKey )
    5 AND NOT EXISTS (SELECT 1 FROM TAB3 phs where phs.PKey = p.AgilityKey )
    6 AND p.rflag = 'Y';
    COUNT(1)
    1
    Elapsed: 00:00:00.52
    Can you give me some tips on where I could read about learning to understand the explain plan. I did read a few articles which did help me, but not much. I am looking for something in detail.

  • FILTER access path..

    Hi ,
    I have read a section in Performance Tuning e-book regarding the "Use of EXISTS versus IN for Subqueries".
    In this section an example with its explain plan is posed....
    SELECT
    e.employee_id, e.first_name, e.last_name, e.salary
    FROM employees e
    WHERE EXISTS (SELECT 1 FROM orders o
    WHERE e.employee_id = o.sales_rep_id
    AND o.customer_id = 144);
    ID OPERATION OPTIONS OBJECT_NAME OPT COST
    0 SELECT STATEMENT CHO
    1 FILTER
    2 TABLE ACCESS FULL EMPLOYEES ANA 155
    3 TABLE ACCESS BY INDEX ROWID ORDERS ANA 3
    4 INDEX RANGE SCAN ORD_CUSTOMER_IX ANA 1As this type of access path is not described , at least in this section, can somebody describe when is this used....????
    NOTE: I use Oracle10g. v2
    Thank you....
    Sim

    It does say "The plan requires a full table scan of the employees table, returning many rows. Each of these rows is then filtered against the orders table (through an index)." The FILTER operation consists of working through one set of rows performing some test against it, in this case an index lookup.
    I'm a little surprised at those examples though. In 11g (using the predefined "OE" demo schema) I get the same plan for both versions:
    | Id  | Operation                      | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT               |                 |     3 |    90 |     5  (20)| 00:00:01 |
    |   1 |  NESTED LOOPS                  |                 |       |       |            |          |
    |   2 |   NESTED LOOPS                 |                 |     3 |    90 |     5  (20)| 00:00:01 |
    |   3 |    SORT UNIQUE                 |                 |     3 |    21 |     2   (0)| 00:00:01 |
    |*  4 |     TABLE ACCESS BY INDEX ROWID| ORDERS          |     3 |    21 |     2   (0)| 00:00:01 |
    |*  5 |      INDEX RANGE SCAN          | ORD_CUSTOMER_IX |     5 |       |     1   (0)| 00:00:01 |
    |*  6 |    INDEX UNIQUE SCAN           | EMP_EMP_ID_PK   |     1 |       |     0   (0)| 00:00:01 |
    |   7 |   TABLE ACCESS BY INDEX ROWID  | EMPLOYEES       |     1 |    23 |     1   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       4 - filter("O"."SALES_REP_ID" IS NOT NULL)
       5 - access("O"."CUSTOMER_ID"=144)
       6 - access("E"."EMPLOYEE_ID"="O"."SALES_REP_ID")I haven't tested in 10g but I would expect similar results. If you can use either IN or EXISTS without affecting the logic, so can the optimizer.

  • PARTITION RANGE SUBQUERY - Access path

    Below quote is from Oracle product documentation.
    <quote>
    If the table with the WHERE predicate is relatively small compared to the partitioned table, and the expected reduction of records or partitions for the partitioned table is significant, Oracle will perform dynamic partition pruning using a recursive subquery
    </quote>
    http://download.oracle.com/docs/cd/B19306_01/server.102/b14223/parpart.htm#sthref215
    create table t(
         x number,
         y number,
         z number
    ) partition by range(z)
         partition p_10 values less than ( 11),
         partition p_20 values less than ( 21),
         partition p_30 values less than ( 31),
         partition p_40 values less than ( 41),
         partition p_50 values less than ( 51),
         partition p_60 values less than ( 61),
         partition p_70 values less than ( 71),
         partition p_80 values less than ( 81),
         partition p_90 values less than ( 91),
         partition p_100 values less than ( 101)
    create table t1
    as
    select mod(rownum,10) as id,
         username ,
         sysdate as dt
    from all_users;     
    insert /*+ append */ into t
    select level,level,10
    from dual
    connect by level <= 1000000;
    commit;
    insert /*+ append */ into t select x,y,20 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,30 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,40 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,50 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,60 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,70 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,80 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,90 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,100 from t partition (p_10);
    commit;
    begin
         dbms_stats.gather_table_Stats(user,'T1');
         dbms_stats.gather_table_stats(ownname=>user,tabname=>'T',degree=>16);
    end;
    select /*+ use_hash(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and t1.username ='SCOTT'
    call count cpu elapsed disk query current rows
    Parse 1 0.03 0.67 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 1 0.65 0.65 0 2507 0 0
    total 3 0.68 1.32 0 2507 0 0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100
    Rows Row Source Operation
    0 HASH JOIN (cr=2510 pr=0 pw=0 time=653031 us)
    1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=59 us)
    1000000 PARTITION RANGE SUBQUERY PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2507 pr=0 pw=0 t
    1000000 TABLE ACCESS FULL T PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2504 pr=0 pw=0 t
    select /*+ use_nl(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and t1.username ='SCOTT'
    call count cpu elapsed disk query current rows
    Parse 1 0.00 0.00 0 0 0 0
    Execute 1 0.00 0.00 0 0 0 0
    Fetch 1 0.12 0.12 0 2506 0 0
    total 3 0.12 0.12 0 2506 0 0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100
    Rows Row Source Operation
    0 NESTED LOOPS (cr=2506 pr=0 pw=0 time=123836 us)
    1 TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=53 us)
    0 PARTITION RANGE ITERATOR PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123777 us)
    0 TABLE ACCESS FULL T PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123761 us)
    Questions_
    1) what is the significant in having this PARTITION RANGE SUBQUERY access path in Oracle 10g? Even reading documentation, still unclear.
    Edited by: Rajeshwaran on Nov 15, 2010 8:05 AM

    Yep..Here is the code.
    create table t(
         x number,
         y number,
         z number
    ) partition by range(z)
         partition p_10 values less than ( 11),
         partition p_20 values less than ( 21),
         partition p_30 values less than ( 31),
         partition p_40 values less than ( 41),
         partition p_50 values less than ( 51),
         partition p_60 values less than ( 61),
         partition p_70 values less than ( 71),
         partition p_80 values less than ( 81),
         partition p_90 values less than ( 91),
         partition p_100 values less than ( 101)
    create table t1
    as
    select mod(rownum,10) as id,
            username ,
            sysdate as dt
    from all_users;       
    insert /*+ append */ into t
    select level,level,10
    from dual
    connect by level <= 1000000;
    commit;
    insert /*+ append */ into t select x,y,20 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,30 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,40 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,50 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,60 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,70 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,80 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,90 from t partition (p_10);
    commit;
    insert /*+ append */ into t select x,y,100 from t partition (p_10);
    commit;
    begin
         dbms_stats.gather_table_Stats(user,'T1');
         dbms_stats.gather_table_stats(ownname=>user,tabname=>'T',degree=>16);
    end;
    select /*+ use_hash(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and   t1.username ='SCOTT'
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.03       0.67          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        1      0.65       0.65          0       2507          0           0
    total        3      0.68       1.32          0       2507          0           0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100 
    Rows     Row Source Operation
          0  HASH JOIN  (cr=2510 pr=0 pw=0 time=653031 us)
          1   TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=59 us)
    1000000   PARTITION RANGE SUBQUERY PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2507 pr=0 pw=0 t
    1000000    TABLE ACCESS FULL T PARTITION: KEY(SUBQUERY) KEY(SUBQUERY) (cr=2504 pr=0 pw=0 t
    select /*+ use_nl(t,t1) */ t.*
    from t, t1
    where t.z = t1.id
    and   t1.username ='SCOTT'
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.00       0.00          0          0          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch        1      0.12       0.12          0       2506          0           0
    total        3      0.12       0.12          0       2506          0           0
    Misses in library cache during parse: 1
    Optimizer mode: ALL_ROWS
    Parsing user id: 100 
    Rows     Row Source Operation
          0  NESTED LOOPS  (cr=2506 pr=0 pw=0 time=123836 us)
          1   TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=53 us)
          0   PARTITION RANGE ITERATOR PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123777 us)
          0    TABLE ACCESS FULL T PARTITION: KEY KEY (cr=2503 pr=0 pw=0 time=123761 us)

  • Why the query access path is different !

    Hi All
    I have a query which is running satisfactorily in TEST but is taking a long time in PROD.
    SELECT * FROM MTHLY_PROD_BASE WHERE START_DATE >= to_date('1/1/2013','mm/dd/yyyy') AND START_DATE < to_date('1/1/2014','mm/dd/yyyy')
    MTHLY_PROD_BASE is a view, containing some underlying tables and views which are doing summations and groupings of data.
    I have access plans for it in TEST and PROD in jpg format, but I am not able to attach here as the "Insert Image" button is inactive for me. How can I attach them for explaining my issue properly ?
    There was some memory added around a week ago to the DB server for improving performance of another database, but since then the DB in which I ran the query is performing poorly.
    Data for underlying tables, being referenced in the query, in TEST is same as in PROD, but the plans are different.
    I need to know what factors may cause the access path for a query to change, so that I can investigate what else might have got changed/impacted in PROD ?
    Thanks

    AnkitV wrote:
    Hi all
    1) version info of TEST and PROD:
    Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
    PL/SQL Release 11.2.0.2.0 - Production
    "CORE    11.2.0.2.0    Production"
    TNS for IBM/AIX RISC System/6000: Version 11.2.0.2.0 - Production
    NLSRTL Version 11.2.0.2.0 - Production
    2) Platform is Aix 6.1.0.0
    3) Query as mentioned in initial post too :SELECT * FROM MTHLY_PROD_BASE WHERE START_DATE >= to_date('1/1/2013','mm/dd/yyyy') AND START_DATE < to_date('1/1/2014','mm/dd/yyyy')
    4) As I mentioned, I do not have plan in text format, and its lots of lines in the
    I need to know what might be the reason for change in the access mode for the query in PROD, which has caused it to take 3-4 hrs instead of 30 mins ?
    Any help will be highly appreciated.
    different results occur when something is different between the two environments.
    Since we don't have access to either system, YOU are the only one who can actually compare & contrast between the two systems.
    HOW To Make TUNING request
    https://forums.oracle.com/forums/thread.jspa?threadID=2174552#9360003

  • Access path difference between Primary Key and Unique Index

    Hi All,
    Is there any specific way the oracle optimizer treats Primary key and Unique index differently?
    Oracle Version
    SQL> select * from v$version;
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
    PL/SQL Release 11.2.0.3.0 - Production
    CORE    11.2.0.3.0      Production
    TNS for IBM/AIX RISC System/6000: Version 11.2.0.3.0 - Production
    NLSRTL Version 11.2.0.3.0 - Production
    SQL> Sample test data for Normal Index
    SQL> create table t_test_tab(col1 number, col2 number, col3 varchar2(12));
    Table created.
    SQL> create sequence seq_t_test_tab start with 1 increment by 1 ;
    Sequence created.
    SQL>  insert into t_test_tab select seq_t_test_tab.nextval, round(dbms_random.value(1,999)) , 'B'||round(dbms_random.value(1,50))||'A' from dual connect by level < 100000;
    99999 rows created.
    SQL> commit;
    Commit complete.
    SQL> exec dbms_stats.gather_table_stats(USER_OWNER','T_TEST_TAB',cascade => true);
    PL/SQL procedure successfully completed.
    SQL> select col1 from t_test_tab;
    99999 rows selected.
    Execution Plan
    Plan hash value: 1565504962
    | Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |            | 99999 |   488K|    74   (3)| 00:00:01 |
    |   1 |  TABLE ACCESS FULL| T_TEST_TAB | 99999 |   488K|    74   (3)| 00:00:01 |
    Statistics
              1  recursive calls
              0  db block gets
           6915  consistent gets
            259  physical reads
              0  redo size
        1829388  bytes sent via SQL*Net to client
          73850  bytes received via SQL*Net from client
           6668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          99999  rows processed
    SQL> create index idx_t_test_tab on t_test_tab(col1);
    Index created.
    SQL> exec dbms_stats.gather_table_stats('USER_OWNER','T_TEST_TAB',cascade => true);
    PL/SQL procedure successfully completed.
    SQL> select col1 from t_test_tab;
    99999 rows selected.
    Execution Plan
    Plan hash value: 1565504962
    | Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |            | 99999 |   488K|    74   (3)| 00:00:01 |
    |   1 |  TABLE ACCESS FULL| T_TEST_TAB | 99999 |   488K|    74   (3)| 00:00:01 |
    Statistics
              1  recursive calls
              0  db block gets
           6915  consistent gets
              0  physical reads
              0  redo size
        1829388  bytes sent via SQL*Net to client
          73850  bytes received via SQL*Net from client
           6668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          99999  rows processed
    SQL> Sample test data when using Primary Key
    SQL> create table t_test_tab1(col1 number, col2 number, col3 varchar2(12));
    Table created.
    SQL> create sequence seq_t_test_tab1 start with 1 increment by 1 ;
    Sequence created.
    SQL> insert into t_test_tab1 select seq_t_test_tab1.nextval, round(dbms_random.value(1,999)) , 'B'||round(dbms_random.value(1,50))||'A' from dual connect by level < 100000;
    99999 rows created.
    SQL> commit;
    Commit complete.
    SQL> exec dbms_stats.gather_table_stats('USER_OWNER','T_TEST_TAB1',cascade => true);
    PL/SQL procedure successfully completed.
    SQL> select col1 from t_test_tab1;
    99999 rows selected.
    Execution Plan
    Plan hash value: 1727568366
    | Id  | Operation         | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |             | 99999 |   488K|    74   (3)| 00:00:01 |
    |   1 |  TABLE ACCESS FULL| T_TEST_TAB1 | 99999 |   488K|    74   (3)| 00:00:01 |
    Statistics
              1  recursive calls
              0  db block gets
           6915  consistent gets
              0  physical reads
              0  redo size
        1829388  bytes sent via SQL*Net to client
          73850  bytes received via SQL*Net from client
           6668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          99999  rows processed
    SQL> alter table t_test_tab1 add constraint pk_t_test_tab1 primary key (col1);
    Table altered.
    SQL> exec dbms_stats.gather_table_stats('USER_OWNER','T_TEST_TAB1',cascade => true);
    PL/SQL procedure successfully completed.
    SQL> select col1 from t_test_tab1;
    99999 rows selected.
    Execution Plan
    Plan hash value: 2995826579
    | Id  | Operation            | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |                | 99999 |   488K|    59   (2)| 00:00:01 |
    |   1 |  INDEX FAST FULL SCAN| PK_T_TEST_TAB1 | 99999 |   488K|    59   (2)| 00:00:01 |
    Statistics
              1  recursive calls
              0  db block gets
           6867  consistent gets
              0  physical reads
              0  redo size
        1829388  bytes sent via SQL*Net to client
          73850  bytes received via SQL*Net from client
           6668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          99999  rows processed
    SQL> If you see here the even though statistics were gathered,
         * In the 1st table T_TEST_TAB, the table is still using FULL table access after creation of index.
         * And in the 2nd table T_TEST_TAB1, table is using PRIMARY KEY as expected.
    Any comments ??
    Regards,
    BPat

    Thanks.
    Yes, ignored the NOT NULL part.Did a test and now it is working as expected
    SQL>  create table t_test_tab(col1 number not null, col2 number, col3 varchar2(12));
    Table created.
    SQL>
    create sequence seq_t_test_tab start with 1 increment by 1 ;SQL>
    Sequence created.
    SQL> insert into t_test_tab select seq_t_test_tab.nextval, round(dbms_random.value(1,999)) , 'B'||round(dbms_random.value(1,50))||'A' from dual connect by level < 100000;
    99999 rows created.
    SQL> commit;
    Commit complete.
    SQL>  exec dbms_stats.gather_table_stats('GREP_OWNER','T_TEST_TAB',cascade => true);
    PL/SQL procedure successfully completed.
    SQL>  set autotrace traceonly
    SQL>  select col1 from t_test_tab;
    99999 rows selected.
    Execution Plan
    Plan hash value: 1565504962
    | Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT  |            | 99999 |   488K|    74   (3)| 00:00:01 |
    |   1 |  TABLE ACCESS FULL| T_TEST_TAB | 99999 |   488K|    74   (3)| 00:00:01 |
    Statistics
              1  recursive calls
              0  db block gets
           6912  consistent gets
              0  physical reads
              0  redo size
        1829388  bytes sent via SQL*Net to client
          73850  bytes received via SQL*Net from client
           6668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          99999  rows processed
    SQL>  create index idx_t_test_tab on t_test_tab(col1);
    Index created.
    SQL>  exec dbms_stats.gather_table_stats('GREP_OWNER','T_TEST_TAB',cascade => true);
    PL/SQL procedure successfully completed.
    SQL>  select col1 from t_test_tab;
    99999 rows selected.
    Execution Plan
    Plan hash value: 4115006285
    | Id  | Operation            | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT     |                | 99999 |   488K|    63   (2)| 00:00:01 |
    |   1 |  INDEX FAST FULL SCAN| IDX_T_TEST_TAB | 99999 |   488K|    63   (2)| 00:00:01 |
    Statistics
              1  recursive calls
              0  db block gets
           6881  consistent gets
              0  physical reads
              0  redo size
        1829388  bytes sent via SQL*Net to client
          73850  bytes received via SQL*Net from client
           6668  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
          99999  rows processed
    SQL>

  • INDEX UNIQUE SCAN instead of   INDEX FULL SCAN or TABLE ACCESS FULL

    I have calculated statistics in all tables and indexes
    I have a table and a view and when I put it
    SELECT *
    FROM TABLE_A A
    INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID          
    WHERE (B.FK_ID_XXX = 1)
    If I see the execution plan:
    In TABLE_A make a
    TABLE ACCESS BY INDEX ROWID
    INDEX UNIQUE SCAN (FIELD_A_TABLE_A_PK)
    It’s OK. I NEED IT (INDEX UNIQUE SCAN)
    But If I put
    SELECT A.Field_1, A.Field_2, A.Field_3, A.Field_4
    FROM TABLE_A A
    INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID          
    WHERE (B.FK_ID_XXX = 1)
    In table A make a TABLE ACCESS FULL.
    Then If I put:
    SELECT /*+ INDEX(A FIELD_A_TABLE_A_PK) */ A.Field_1, A.Field_2, A.Field_3, A.Field_4
    FROM TABLE_A A
    INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID          
    WHERE (B.FK_ID_XXX = 1)
    If I see the execution plan:
    In TABLE_A make a
    TABLE ACCESS BY INDEX ROWID
    INDEX UNIQUE SCAN (FIELD_A_TABLE_A_PK)
    It’s OK. I NEED IT (INDEX UNIQUE SCAN)
    Finally, If I put other tables and views in the query (I NEED IT)
    For example:
    SELECT /*+ INDEX(A FIELD_A_TABLE_A_PK) */ A.Field_1, A.Field_2, A.Field_3, A.Field_4
    FROM TABLE_A A
    INNER JOIN VIEW_B B ON A.KEY_ID = B.PFK_KEY_ID          
    INNER JOIN TABLE_C….
    LEFT JOIN VIEW_D….
    WHERE (B.FK_ID_XXX = 1)
    If I see the execution plan:
    In TABLE_A make a
    TABLE ACCESS BY INDEX ROWID
    INDEX FULL SCAN (FIELD_A_TABLE_A_PK)
    I need INDEX UNIQUE SCAN instead of INDEX FULL SCAN or TABLE ACCESS FULL.
    How can obtain it?
    What happens???
    Thanks!

    Notice the difference in cardinality between your two select statements:
    SELECT STATEMENT, GOAL = ALL_ROWS Cost=5 Cardinality=1
    SELECT STATEMENT, GOAL = ALL_ROWS Cost=10450 Cardinality=472161Apparently since the optimizer believed the first statement was going to return one row, it used an index. But in the second statement it believed it was going to return nearly the whole table (didn't you say it had around 500k rows?). Hence full table scan.

  • How to change access path for 'where' clause by using HINTS?

    I searched a loooot of posts and haven't found a solution for my case. I don't even know whether it is possible or not. Is it possible to change the sequence of Oracle "Predicate Information"?
    Here is my SQL and Oracle's execution plan.
      SELECT Max(logId) AS logId FROM online_users_t
      WHERE online_users_date >= to_date('2011-09-19 10:00:00') - 3.2 AND online_users_date <= to_date('2011-09-19 10:00:00') AND online_users_result in (1, -1)
      GROUP BY online_users_user
    | Id  | Operation                    | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT             |                    | 24800 |   629K|  1336   (1)| 00:00:17 |
    |   1 |  HASH GROUP BY               |                    | 24800 |   629K|  1336   (1)| 00:00:17 |
    |*  2 |   TABLE ACCESS BY INDEX ROWID| ONLINE_USERS_T     | 38833 |   985K|  1334   (1)| 00:00:17 |
    |*  3 |    INDEX RANGE SCAN          | ONLINE_USERS_T_IDX |   116K|       |   313   (1)| 00:00:04 |
    Predicate Information (identified by operation id):
       2 - filter("ONLINE_USERS_RESULT"=(-1) OR "ONLINE_USERS_RESULT"=1)
       3 - access("ONLINE_USERS_DATE">=TO_DATE(' 2011-09-16 05:12:00', 'syyyy-mm-dd
                  hh24:mi:ss') AND "ONLINE_USERS_DATE"<=TO_DATE(' 2011-09-19 10:00:00', 'syyyy-mm-dd
                  hh24:mi:ss'))I have 2 conditions in my 'where' clause, one is date range and the other is 'online_users_result in (1, -1)'. It seems that Oracle filter the table by using 'online_users_result in (1, -1)' first, then access it through date range.
    What I want to do is firstly filtering the table by using date range followed by other things. How can I do it?
    Any clue or help would be highly appreciated.
    Thanks in advance.

    It seems that Oracle filter the table by using 'online_users_result in (1, -1)' first, then access it through date range. No it's not.
    What I want to do is firstly filtering the table by using date range followed by other things. How can I do it?That's precisely what it's doing now.
    It is using the T_IDX index to quickly find all rows that satisfy the range predicate on the date column.
    And then filter those rows to only retrieve the ones that satisfy the other predicate (... in (1,-1)).

  • Using index in a query return few records than full table access

    Today we have an issue with a query, when it use the ok index the returned are not all records that apply to where clause condition.
    See bellow
    explain plan for
    select * from movdb.zan_m03 where
    M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
    M00za = 10 AND
    m00AC = 50 AND
    M00AD between 136906 and 136999
    SELECT * FROM TABLE(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    Plan hash value: 1882720105
    | Id | Operation | Name |
    | 0 | SELECT STATEMENT | |
    | 1 | TABLE ACCESS BY INDEX ROWID| ZAN_M03 |
    |* 2 | INDEX RANGE SCAN | PK_ZAN_M03 |
    Predicate Information (identified by operation id):
    PLAN_TABLE_OUTPUT
    2 - access("M00AF"=TO_DATE('11/01/28','YY/MM/DD') AND "M00ZA"=10 AND
    "M00AC"=50 AND "M00AD">=136906 AND "M00AD"<=137141)
    filter("M00AD"<=137141 AND "M00AD">=136906)
    Note
    - rule based optimizer used (consider using cbo)
    20 rows selected.
    The query above return only one row insted 1579 record that apply to this conditions.
    When forcing a full table acess with a hint, the query return all records that apply, the 1579 record.
    select /*+ FULL(zan_m03) */ M00AF, M00za, m00AC , M00AD from movdb.zan_m03 where
    M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
    M00za = 10 AND
    m00AC = 50 AND
    M00AD between 136906 and 137141
    Can you help me to identify what's happening?
    I am with Oracle 10g R2 10.2.0.4 standard edition
    the statistics are up to date
    the opitimizer_mode are rule, but altering in session level to all_rows happens the same issue.
    Nothing about corruption in the alert log.
    Thanks in advance
    Regards
    Cristiano

    Yes the query are the same and correct restriction for where clause are M00AD between 136906 and 137141.
    I've pasted, by mistake, another test query
    The corrects are:
    select M00AF, M00za, m00AC , M00AD from movdb.zan_m03 where
    M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
    M00za = 10 AND
    m00AC = 50 AND
    M00AD between 136906 and 137141
    This use pk index and return one row
    select /*+ FULL(zan_m03) */ M00AF, M00za, m00AC , M00AD from movdb.zan_m03 where
    M00AF = TO_DATE('11/01/28','YY/MM/DD') AND
    M00za = 10 AND
    m00AC = 50 AND
    M00AD between 136906 and 137141
    This does a full table access and return 1579 records
    I´ve been searching for wrong results bugs on my oracle support, but not found one that mentions something like our issue.
    I checked the dba_tables and dba indexes and the number of rows are different, and I think this would be the same because it's is a pk.
    Look this
    SQL> select NUM_ROWS from dba_tables where table_name = 'ZAN_M03'
    2 /
    NUM_ROWS
    228527878
    select NUM_ROWS from dba_indexes where index_name = 'PK_ZAN_M03';
    SQL> select NUM_ROWS from dba_indexes where index_name = 'PK_ZAN_M03';
    NUM_ROWS
    217510185
    Is normal a index for pk having much fewer rows than table? I think not, but not sure.
    Again
    Thanks in advance
    Regards
    Cristiano

  • Table access by index rowid taking more time

    Hi All
    I've a query like
    update tab1
      set col1 = ( select col2 from
                           tab2 
                    where tab1.id = tab2.id) table 1 has arnd 10,000 rows
    table 2 has arnd 1,700,000 rows and has a primay key on column id.
    This query is taking around 20 secs to execute. I checked the xplan and most of time taken for table access by index rowid.
    Could you please suggest what can be the reason for this. (Can it be the clustering factor or something else)
    I checked the stats for the tab2, its just three days old.
    Regards
    Ashwani

    >
    table 1 has arnd 10,000 rows
    table 2 has arnd 1,700,000 rows and has a primay key on column id.
    This query is taking around 20 secs to execute. I checked the xplan and most of time taken for table access by index rowid.
    Could you please suggest what can be the reason for this. (Can it be the clustering factor or something else)
    I checked the stats for the tab2, its just three days old.
    >
    If you checked the xplan why haven't you posted it so we can look at it? Then we could see what table is being accessed by index rowid. Presumably it is table 2 but we the plan would eliminate the need to make assumptions.
    The clustering factor could be a factor. You haven't told us how table1 is being accessed. All rows are being updated so a full table scann is most likely but again the plan would actually show the access.
    Did you query the dictionary to see what the clustering factor is? Post the results of that
    SQL> select index_name, leaf_blocks, avg_leaf_blocks_per_key, avg_data_blocks_per_key, clustering_factor, distinct_keys
    2 from dba_indexes
    3 where owner = 'schema'
    4 and index_name in ('index_b','index_a');

  • Oracle 9.2 prefers Table Access Full over Local Index by rowid access

    There's this table that has phone call records (30 million per day) that is partitioned by month (using the date column) and stores the last 6 months.
    The primary key is date (varchar2 in yymmdd format) + call_id (a varchar2(18) with a format like this yyyymmdd+<3letters>+<sequentialnumber>)
    The partition is by range like this:
    PARTITION BY RANGE (FECHA)
    PARTITION P200804 VALUES LESS THAN ('080501')
    LOGGING
    NOCOMPRESS,
    If I run this query I get this plan
    SELECT FECHA, SENTIDOTRAFICO,GEOGRAFIAID,SWITCHID,TIPOTRAFICOID,COUNT(*)
    FROM GES_CDRS_RCNG_NEW
    WHERE FECHA BETWEEN '080801' AND '080825'
         AND TASACION IS NULL
         AND BORRADO IS NULL
    GROUP BY FECHA, SENTIDOTRAFICO,GEOGRAFIAID,SWITCHID,TIPOTRAFICOID
    Plan
    SELECT STATEMENT CHOOSECost: 78 K Bytes: 24 K Cardinality: 1 K           
         2 SORT GROUP BY Cost: 78 K Bytes: 24 K Cardinality: 1 K      
              1 TABLE ACCESS FULL GESTION.GES_CDRS_RCNG_NEW Cost: 43 K Bytes: 625 M Cardinality: 31 M Partition #: 2 Partitions accessed #5
    If I hint the primary key index using /*+INDEX(GES_CDRS_RCNG_NEW PK_CDRS_RCNG_NEW)*/
    I get a different plan
    Plan
    SELECT STATEMENT CHOOSECost: 954 K Bytes: 24 K Cardinality: 1 K                
         3 SORT GROUP BY Cost: 954 K Bytes: 24 K Cardinality: 1 K           
              2 TABLE ACCESS BY LOCAL INDEX ROWID GESTION.GES_CDRS_RCNG_NEW Cost: 918 K Bytes: 625 M Cardinality: 31 M Partition #: 2 Partitions accessed #5     
                   1 INDEX RANGE SCAN UNIQUE GESTION.PK_CDRS_RCNG_NEW Cost: 137 K Cardinality: 31 M Partition #: 3 Partitions accessed #5
    Looking at the cost, the full scan is way better, but this is obviously not the case. Why does this happen?
    This problem forces many querys on this table to use hints or force the index use by adding conditions to the where clause like this
    where fecha = '080801'
    and clave like '20080801%'
    when just by stating the date would be enough to choose the correct partition. It also messes up joins with other tables.
    The table is analized every month, it has statistics that claim: 237,981,000 rows, 3,222,677 blocks, GLOBAL STATS: YES, LAST ANALYZED: 15/10/2008 21:05:26, Average row length: 213.
    The partition envolved in this query has this stats: 32,520,520 rows, 442,715 blocks, analized on 27/08/2008 20:43:40
    The index has this stats: analized on 15/10/2008 21:35:32, Blevel: 3, leaf blocks: 1,056,410, distinct keys: 238,484,510.
    It is a local index and each partition has its own statistics.

    If I don't understand incorrectly the plan and the Predicater information, it seems the full scan version that costs less is actually doing a full scan from the biggining of the table (6 months) up to the 080825 date and the one using an index (hinted) does a better scan.
    without hint
    | Id  | Operation            |  Name              | Rows  | Bytes | Cost  | Pstart| Pstop |
    |   0 | SELECT STATEMENT     |                    |  1170 | 24570 | 78443 |       |       |
    |   1 |  SORT GROUP BY       |                    |  1170 | 24570 | 78443 |       |       |
    |*  2 |   TABLE ACCESS FULL  | GES_CDRS_RCNG_NEW  |    31M|   625M| 42579 |     5 |     5 |
    Predicate Information (identified by operation id):
       2 - filter("GES_CDRS_RCNG_NEW"."FECHA"<='080825')
    Note: cpu costing is offWith the hint:
    | Id  | Operation                          |  Name              | Rows  | Bytes | Cost  | Pstart| Pstop |
    |   0 | SELECT STATEMENT                   |                    |  1170 | 24570 |   953K|       |       |
    |   1 |  SORT GROUP BY                     |                    |  1170 | 24570 |   953K|       |       |
    |   2 |   TABLE ACCESS BY LOCAL INDEX ROWID| GES_CDRS_RCNG_NEW  |    31M|   625M|   918K|     5 |     5 |
    |*  3 |    INDEX RANGE SCAN                | PK_CDRS_RCNG_NEW   |    31M|       |   136K|     5 |     5 |
    Predicate Information (identified by operation id):
       3 - access("GES_CDRS_RCNG_NEW"."FECHA">='080801' AND "GES_CDRS_RCNG_NEW"."FECHA"<='080825')
    Note: cpu costing is off

  • Export table access to oracle with Database ODBC()

    Hi,
    I export a table, access 2003, ent_tab whit  'DataBase ODBC()' to oracle.
    I open Oracle SQL Developer and i can show table ent_tab, but i go worksheet and execute:
    select * from ent_tab
    and display error: ORA-00942...
    Why??!!
    Regards
    Jomar

    Because ODBC created the table with "" which allowed lower case table name, but Oracle uses upper case table name by default. Suggest you recreate the table with upper-case name to avoid having to use "" in select statements.
    Edited by: rgeier on Oct 27, 2009 5:34 PM

  • Excluding slow table access in a UNION ALL view

    Hi,
    I have a view which unions three tables together.
    One component of the view requires a table scan, as 90% of the records are required.
    This view is then used in another outer select where these records are actually not required.
    So I tagged each component with a code and excluded that in the outer select. However it still appears to access the table.
    Is there any way I can exclude a component of the UNION ALL or do I need to explicitly split them?
    example:
    SELECT * FROM (
    SELECT 'A' Q, JANUARY F FROM ENORMOUS.TABLE WHERE KEY = 'Non Selective Key' UNION ALL
    SELECT 'B' Q, 1 F FROM DUAL UNION ALL
    SELECT 'C' Q, 1 F FROM DUAL
    ) A
    WHERE Q = 'B'
    When I run the query plan without the WHERE it performs the table scan
    When I include the WHERE it still performs the table scan but with a FILTER NULL IS NOT NULL afterwards.
    So it appears that it is doing the table scan regardless and then throwing the records away - is that correct?
    Any thoughts appreciated. I would prefer not the split this view out if possible as it is used everywhere.

    In summary my question is: is The Oracle query planner smart enough to exclude a component from a load of stacked UNION ALL queries?
    given this query:
    CREATE VIEW TEST AS
    SELECT Q, F
    FROM
    SELECT 'A' Q, JANUARY F FROM ENORMOUS.TABLE WHERE KEY = 'Non Selective Key' UNION ALL
    SELECT 'B' Q, 1 F FROM DUAL UNION ALL
    SELECT 'C' Q, 1 F FROM DUAL
    ) A;
    -- 1. This one selects from all tables, including a table scan on the enormous table
    SELECT * FROM TEST;
    -- 2. This one selects from all tables, including a table scan on the enormous table
    -- However the query plan has a FILTER after the table scan. Does it exclude this work?
    SELECT * FROM TEST WHERE Q = 'B';When I run the query plan without the WHERE it performs the table scan
    When I include the WHERE the query plan indicates it's doing the table scan but with a FILTER NULL IS NOT NULL afterwards.
    So it appears that it is doing the table scan regardless and then throwing the records away - is that correct?
    Any thoughts appreciated. I would prefer not the split this view out if possible as it is used everywhere.
    Oracle version:
    Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
    PL/SQL Release 11.2.0.2.0 - Production
    CORE     11.2.0.2.0     Production
    TNS for 64-bit Windows: Version 11.2.0.2.0 - Production
    NLSRTL Version 11.2.0.2.0 - Production
    Plan output for 1:
    SELECT STATEMENT Optimizer Mode=ALL_ROWS (Cost=7166 Card=2 M Bytes=41 M)
    1 VIEW (Cost=7166 Card=2 M Bytes=41 M)
    2 1 UNION-ALL
    3 2 TABLE ACCESS FULL PLANNING.BF_GEN_STATS_TRAN (Cost=7162 Card=2 M Bytes=72 M)
    4 2 FAST DUAL (Cost=2 Card=1)
    5 2 FAST DUAL (Cost=2 Card=1)
    Plan output for 2:
    SELECT STATEMENT Optimizer Mode=ALL_ROWS (Cost=2 Card=3 Bytes=48)
    1 VIEW (Cost=2 Card=3 Bytes=48)
    2 1 UNION-ALL
    3 2 FILTER
    4 3 TABLE ACCESS FULL PLANNING.BF_GEN_STATS_TRAN (Cost=7162 Card=2 M Bytes=72 M)
    5 2 FAST DUAL (Cost=2 Card=1)
    6 2 FILTER
    7 6 FAST DUAL (Cost=2 Card=1)

  • Need to reduce table accesses

    oracle 9.2.0.8 (if there's a 10G way that would work)
    This is a simplified view of a much biiger table I am having to deal with.
    create table stg
    (ddate date,
    num number);
    insert into stg
    select sysdate, 26 from dual
    union all
    select sysdate - 1, 38 from dual
    union all
    select sysdate - 2, 10 from dual
    union all
    select sysdate - 3, 40 from dual
    union all
    select sysdate - 4, 50 from dual
    union all
    select sysdate - 5, 1 from dual
    union all
    select sysdate - 6, 11 from dual
    union all
    select sysdate - 7, 50 from dual
    union all
    select sysdate - 9, 38 from dual
    union all
    select sysdate - 10, 20 from dual
    union all
    select sysdate - 11, 11 from dual
    union all
    select sysdate - 12, 99 from dual
    union all
    select sysdate - 13, 18 from dual
    union all
    select sysdate - 14, 27 from dual
    union all
    select sysdate - 15, 28 from dual
    union all
    select sysdate - 16, 2 from dual
    union all
    select sysdate - 17, 99 from dual
    union all
    select sysdate - 18, 12 from dual
    union all
    select sysdate - 19, 27 from dual
    union all
    select sysdate - 20, 28 from dual
    select
    sum(case when ddate > d.the_date then 1
    else 0
    end)
    ,sum(case when ddate < d.the_date then 1
    else 0
    end)
    ,the_date
    ,max(ddate)
    from stg, (select min(ddate) as the_date from stg
    where num in (10,11,12,13,14,25))d
    group by the_date
    the query does give me the result set I'm looking for but the explain plan
    shows it takes 2 table accesses. My question is how to re-write this so it
    takes one access.
    I have tried the analytic functions but there does not seem to be a way to
    use the where clause in just the analytic function. Also I have tried:
    select min(ddate), max(ddate) from stg
    where num in (10,11,12,13,14,25)
    but the problem with this is the max is the max where num is (10,11,12,13,14,25)not the max of the whole table.
    any ideas to get rid of the nested loop would be helpful
    thanks

    What do you want is not clear for me, but you can try to replace your query :
    SCOTT@demo102> select greater,lesser,min_date,max_date
      2  from
      3  (SELECT
      4   SUM(decode(SIGN(ddate -stg_sub."min_date"), 1, 1, 0)) over() AS greater
      5  ,SUM(decode(SIGN(ddate -stg_sub."min_date"), -1, 1, 0)) over() AS lesser
      6  ,stg_sub."min_date" AS min_date
      7  ,stg_sub."max_date" AS max_date
      8  ,rownum AS rnum
      9  FROM
    10  (SELECT
    11      ddate
    12     ,(SELECT MIN(ddate) FROM stg WHERE num IN(10,11,12,13,14,25)) AS "min_date"
    13     ,max(ddate) over() AS "max_date"
    14   FROM stg)stg_sub)
    15  where rnum = 1
    16  ;
       GREATER     LESSER MIN_DATE MAX_DATE
            17          2 26/09/06 14/10/06by
    SCOTT@demo102> select sum(greater) greater, sum(lesser) lesser, max(min_date) min_date, max(max_date) max_date
      2  from
      3  (SELECT
      4     case when ddate - MIN(case when num IN(10,11,12,13,14,25) then ddate end) over () > 0 then 1 end AS greater,
      5     case when ddate - MIN(case when num IN(10,11,12,13,14,25) then ddate end) over () < 0 then 1 end AS lesser,
      6     MIN(case when num IN(10,11,12,13,14,25) then ddate end) over ()  as min_date,
      7     max(ddate) over() AS max_date
      8   FROM stg)
      9  ;
       GREATER     LESSER MIN_DATE MAX_DATE
            17          2 26/09/06 14/10/06
    SCOTT@demo102>
    It is a lower cost What did you mean by cost ? Is it cost from explain plan ? Take care, a low cost here doesn't say that your query will run fatser...
    Nicolas.

Maybe you are looking for

  • Oracle DB Adapter throwing NLS_LANGUAGE' by invoking SP in  BPEL Process

    Hi, While i am invoking a Store procedure, the DB Adapter in BPEL process reslting throwing following below error in <fault> <bpelFault> <faultType>0</faultType> <bindingFault> <part name="summary"> <summary>Exception occured when binding was invoked

  • Copy applications from Apple IPOD Touch to Apple IPHONE

    I purchased me an IPHONE and I have application that I installed from Apple Applications from using the ICON on the IPOD TOUCH. I am interested in know instead of paying again for the same applications can I transfer/copy these applications to the IP

  • Recent items not working

    altought recent items is set to none when I open pictures, texedit or word docs at least 10 previous files open up at the same time this is really confusing and annoying safari 6 still ***** why does mountain lion have the same bugs as the first vers

  • Conditional Build Tags Logic

    Hi All, Working on RH X5 generating webhelp. I need some logic help or some help on developing different manuals for different users for the same system, will explain below. I have got one project which have contents for different version i.e. from 6

  • PowerShell : SPWeb.GetFolder() with browser folder url failed

    I am using powershell script and when I call SPWeb.GetFolder() with (short url) it works fine and when I used (browser url) it's not working. However it refers to the same folder e.g short url http://intranet.company.eg/it/Test/Test browser url : htt