Explain plan doubt.

I have done 'explain plan' for this query:-
explain plan for
select MD.* from ppbs_mobile_detail MD, ppbs_inv_sim_serial ISS where MD.LATEST_SIM_SERIAL_NO=ISS.SIM_SERIAL_NO
and MD.MOBILE_NO=ISS.MOBILE_NO
which is having indexes on all the four columns of the 2 tables used: LATEST_SIM_SERIAL_NO,SIM_SERIAL_NO,MOBILE_NO,
MOBILE_NO.
But only 1 index on mobile no. of ppbs_mobile_detail is firing.
Is that, indexes on only 1 table should fire.
I hope, my question is clear. Please help in solving the doubt.
Regards.

thanks for ur update.
i tried, @?/rdbms/admin/utlxplan.sql but it was giving a error like 'unable to open file "?/rdbms/admin/utlxplan.sql"'.
So, i re-created the table.
I gave both the analyze statements,
SQL> analyze table PPBS_INV_SIM_SERIAL compute statistics for table for all indexed columns for all indexes ;
SQL> analyze table PPBS_MOBILE_DETAIL compute statistics for table for all indexed columns for all indexes ;
Output of select * from TABLE(dbms_xplan.display) is:-
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 1 | 164 | 21174 |
| 1 | HASH JOIN | | 1 | 164 | 21174 |
| 2 | TABLE ACCESS FULL | PPBS_INV_SIM_SERIAL | 3221K| 86M| 9772 |
| 3 | TABLE ACCESS FULL | PPBS_MOBILE_DETAIL | 1469K| 190M| 2718 |
Note: cpu costing is off, PLAN_TABLE' is old version
regards.

Similar Messages

  • Explain plan does not say anything about partition

    Hello,
    We have Oracle 11g database. And we have range partitioned a table. Now when I see explain plans for queries sometimes it says PARTITION RANGE ALL (when no filter), Some times PARTITION RANGE ITERATOR or PARTITION RANGE SINGLE or PARTITION RANGE JOIN FILTER etc. But sometimes it does not say any thing about partition.
    Is the partition pruning being used? Since my understanding is that table is no more a monolithic sort of, but sort of table now has many tables for each partition.
    So option is either scan all partition i.e display PARTITION RANGE ALL or scan some partitions, and display it in explain plan.
    Am I thinking in wrong direction?
    Please let me know.
    Thank you,

    The only thing to do that makes sense is to back up all your data, erase the boot drive, reinstall and update the OS, then restore only your documents from backup and reinstall your third-party software from known-good copies.
    Sadly, this is not practical at the current time. She is away from home, in a place with modem-speed internet access, without access to install media or her backups (which are on a hard drive at home.) I was able to operate on her machine by sshing in, and I did the best I could to remove the crap. The rest will have to wait until she gets back.
    Here is something I found by googling:
    http://nnrpanel.com/offlineAU.htm
    Thank you, I will try them. I doubt they will know anything (since there are no Mac instructions on that page) but maybe they can at least send me to the US center. I have tried the US Nielsen Ratings contact form, three times now, but it appears that either they don't read it or they don't respond to it. It also has a maximum message size of about 250 characters.
    I wonder if it may be related to one of those make money at home - be a secret shopper - review products at your leaisure and make a ton of moneydeals.
    I would tend to doubt it, if only because they are clearly quite effective (or nobody would be running those ads) and yet nobody has reported this anywhere else that I can find.
    I'm going to send some emails and see if I can find someone who knows something.

  • Explain Plan of a query.

    I want to know the concept of this 'Explain Plan' of a query & why it is used. Could u also give the syntax of how a explain plan for a query can be done. Please help in solving the doubt as it is urgent.

    Hi,
    set autotrace traceonly explain or
    -- create your plan table in your schema (only once)
    @ ?/rdbms/admin/utlxplan
    -- populate the plan table for your select
    explain plan for select ...;
    -- display output out of the PLAN_TABLE
    @ ?/rdbms/admin/ultxplsRegards
    Laurent

  • Any room for improvement for this query? Explain Plan attached.

    Is there any room for improvement for this query? Table stats are up-to-date. Any suggestions Query rewrite, addition of indexes,...etc ??
    select sum(CONF
                 when (cd.actl_qty - cd.total_alloc_qty - lsd.Q < 0) then
                  0
                 else
                  cd.actl_qty - cd.total_alloc_qty - lsd.Q
               end)
      from (select sum(reqd_qty) as Q, ITEM_ID as ITEM
              from SHIP_DTL SD
             where exists (select 1
                      from CONF_dtl
                     where CONF_nbr = '1'
                       and ITEM_id = SD.ITEM_id)
             group by ITEM_id) lsd,
           CONF_dtl cd
    where lsd.ITEM = cd.ITEM_id
       and cd.CONF_nbr = '1'Total number of rows in the tables involved
    select count(*) from CONF_DTL;
      COUNT(*)
       1785889
    select count(*) from shp_dtl;
      COUNT(*)
        286675
      Explain Plan
    PLAN_TABLE_OUTPUT
    Plan hash value: 2325658044
    | Id  | Operation                           | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT                    |                    |     1 |    39 |     4  (25)| 00:00:01 |
    |   1 |  SORT AGGREGATE                     |                    |     1 |    39 |            |          |
    |   2 |   VIEW                              |                    |     1 |    39 |     4  (25)| 00:00:01 |
    |   3 |    HASH GROUP BY                    |                    |     1 |   117 |     4  (25)| 00:00:01 |
    |   4 |     TABLE ACCESS BY INDEX ROWID     | SHIP_DTL           |     1 |    15 |     1   (0)| 00:00:01
    |   5 |      NESTED LOOPS                   |                    |     1 |   117 |     3   (0)| 00:00:01 |
    |   6 |       MERGE JOIN CARTESIAN          |                    |     1 |   102 |     2   (0)| 00:00:01 |
    |   7 |        TABLE ACCESS BY INDEX ROWID  | CONF_DTL           |     1 |    70 |     1   (0)| 00:00:01 |
    |*  8 |         INDEX RANGE SCAN            | PK_CONF_DTL        |     1 |       |     1   (0)| 00:00:01 |
    |   9 |        BUFFER SORT                  |                    |     1 |    32 |     1   (0)| 00:00:01 |
    |  10 |         SORT UNIQUE                 |                    |     1 |    32 |     1   (0)| 00:00:01 |
    |  11 |          TABLE ACCESS BY INDEX ROWID| CONF_DTL           |     1 |    32 |     1   (0)| 00:00:01 |
    |* 12 |           INDEX RANGE SCAN          | PK_CONF_DTL        |     1 |       |     1   (0)| 00:00:01 |
    |* 13 |       INDEX RANGE SCAN              | SHIP_DTL_IND_6 |     1 |       |     1   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       8 - access("CD"."CONF_NBR"='1')
      12 - access("CONF_NBR"='1')
      13 - access("ITEM_ID"="SD"."ITEM_ID")
           filter("ITEM_ID"="CD"."ITEM_ID")

    Citizen_2 wrote:
    Is there any room for improvement for this query? Table stats are up-to-date. Any suggestions Query rewrite, addition of indexes,...etc ??You say that the table stats are up-to-date, but is the following assumption of the optimizer correct:
    select count(*)
    from CONF_dtl
    where CONF_nbr = '1';Does this query return a count of 1? I doubt that, but that's what Oracle estimates in the EXPLAIN PLAN output. Based on that assumption you get a cartesian join between the two CONF_DTL table instances, and the result - which is still expected to be one row at most - is then joined to the SHIP_DTL table using a NESTED LOOP.
    If above assumption is incorrect, the number of rows generated by the cartesian join can be tremendous rendering the NESTED LOOP operation quite inefficient.
    You can verify this by using the DBMS_XPLAN.DISPLAY_CURSOR function together with the GATHER_PLAN_STATISTICS hint, if you're already on 10g or later.
    For more information regarding the DISPLAY_CURSOR function, see e.g. here: http://jonathanlewis.wordpress.com/2006/11/09/dbms_xplan-in-10g/
    It will show you the actual cardinalities compared to the estimated cardinalities.
    If the estimate of the optimizer is incorrect, you should find out why. There still might be some issues with the statistics, since this is most obvious reason for incorrect estimates.
    Are your index statistics up-to-date?
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/

  • Explain Plan shows Nested Loops, Is it good or bad?

    Hi All,
    I have a doubt in the explain plan, I would like to know if the Nested Loops , will it degrade the query performance?
    Note: I have pasted only few output that I had taken from the expalin plan.
    Do let me know if there is any article I could read to get clear understanding about the same.
    17 NESTED LOOPS ANTI Cost: 125 Bytes: 186 Cardinality: 1                                                                  
    15 NESTED LOOPS ANTI Cost: 124 Bytes: 166 Cardinality: 1                                                             
    12 NESTED LOOPS Cost: 122 Bytes: 140 Cardinality: 1                                                        
         9 NESTED LOOPS Cost: 121 Bytes: 117 Cardinality: 1           
    Thanks

    Hi,
    there is absolutely nothing wrong about nested loops (NL). It's a very efficient way of combining data from two rowsources. It works pretty much like a regular loop: it takes all rows from one rowsource (the "outer" one) and for each of them it looks up a row matching the join condition in the other rowsource (the "inner" one).
    Note that there are not so many alternatives in Oracle: there are only 3 ways to join data in Oracle, and one of them is used in rather special circumstances (merge join). So normally the choice is between a NL and a hash join. Hash join (HJ) takes the smaller dataset and builds an in-memory lookup table using a hash function on join column(s). Then it goes through the other dataset and as it goes, it applies the hashing function to join column(s) and picks the matching rows from the smaller dataset.
    Actually, hash joins and nested loops are not all that different. The basic mechanism is same: you go through one datasource and as you go, you pick matching rows from the other and do the join. The main difference is that a HJ requires some preparation work (it costs resources to build the in-memory table) and thus HJ are typically associated with less-selective queries and full table scans.
    In your particular case it's nor possible to tell whether or not NL is in order based on just a few rows from the explain plan. We need to know the structure of your tables (the DDL), what kind of data they hold (optimizer stats) and what query you are running to be able to tell.
    Best regards,
    Nikolay

  • Calculating the Size(KB) in the explain plan....

    Hi
    I executed a sql statement in SQL*PLUS and having enabled the tracing in OEM , among others , I read the Size in KiloBytes which the 'TABLE ACCESS FULL' segment of the explain plan returned.....
    This number is 5.998,193KB
    I used the vsize built-in function in order to get the total number in bytes of the physical representation of all the rows (about 53500) ....
    So , I wrote :
    select nvl(sum(vsize(farmak_code)),0)+nvl(sum(vsize(emp_name)),0)+nvl(sum(vsize(category)),0)+ .....+.....
    from mitroo_farmakou
    The result was 5794544 in bytes which is close to 5.998,193KB.
    My question is :
    The computation of the bytes in the explain plan (TABLE ACCESS FULL segment) is done by adding the vsize of all columns....????
    Does anybody Knows...????
    Thanks , a lot
    Simon

    I doubt it. For a large table that would be an incredibly expensive calculation.
    I suspect that it is something closer to:
    SQL> SELECT * FROM incident;
    Execution Plan
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=137 Card=15603 Bytes=6818511)
       1    0   TABLE ACCESS (FULL) OF 'INCIDENT' (Cost=137 Card=15603 Bytes=6818511)
    SQL> SELECT ROUND(num_rows * avg_row_len)
      2  FROM user_tables
      3  WHERE table_name = 'INCIDENT';
    ROUND(NUM_ROWS*AVG_ROW_LEN)
                        6818449HTH
    John

  • Why the explain plan incorrent?

    I have a sql in oracle10.2.03:
    select *
    from (select a.*
    from t_user a, t_message b
    where b.user_id = a.row_id and a.user_type = 1
    order by b.happen_time desc)
    where rownum <= 5
    there are indexes on column a.user_type,b.user_id,b.happen_time, and has been analyzed. a.user_type=1 only have 1/1000 records
    the explain plan is below:
    cost Cardinary Bytes
    SELECT STATEMENT, GOAL = ALL_ROWS 30 5 3790
    COUNT STOPKEY
    VIEW BMTEST 30 6 4548
    NESTED LOOPS 30 6 1158
    TABLE ACCESS BY INDEX ROWID BMTEST T_MESSAGE 13 1524118 24385888
    INDEX FULL SCAN DESCENDING BMTEST IDX_MESSAGE_2 1 168
    TABLE ACCESS BY INDEX ROWID BMTEST T_USER 1 1 177
    INDEX UNIQUE SCAN BMTEST PK_USER 1 1
    Oracle use the index full scan descending on the happen_time. the cost only has 30.
    After I add hint on the sql on the user_id of t_message
    select *
    from (select /*+index (b idx_message_1)*/  a.*
    from t_user a, t_message b
    where b.user_id = a.row_id and a.user_type = 1
    order by b.happen_time desc)
    where rownum <= 5
    the explain plan change to:
    cost Cardinary Bytes
    SELECT STATEMENT, GOAL = ALL_ROWS 5020 5 3790
    COUNT STOPKEY
    VIEW BMTEST 5020 54707 41467906
    SORT ORDER BY STOPKEY 5020 54707 10558451
    TABLE ACCESS BY INDEX ROWID BMTEST T_MESSAGE 26 515 8240
    NESTED LOOPS 2707 54707 10558451
    TABLE ACCESS BY INDEX ROWID BMTEST T_USER 1 106 18762
    INDEX RANGE SCAN BMTEST IDX_USER_2 1 106
    INDEX RANGE SCAN BMTEST IDX_MESSAGE_1 1 515
    INDEX UNIQUE SCAN BMTEST PK_USER 1 1
    The cost is 5020, but the execute usage time only is 100ms, and the first SQL does not add hint usage 20s.
    Why the lower cost waste more time, if the cost caculate is incorrect?
    Edited by: [email protected] on Sep 11, 2008 9:14 PM

    [email protected] wrote:
    But i am afraid i use a misunderstand title for this post,my doubt is why oracle get a large cost with the sql execute few time but get a small cost with the sql execute long time.The cost of a query isn't a particularly good proxy for runtime. It is perfectly reasonable for a query with a cost of 1000 to run more quickly than a query with a cost of 100. The cost of queries is only directly comparable between different plans in the same 10053 trace file.
    [email protected] wrote:
    All the indexed columns are both analyzed by the command or by DBMS_STATS package and the cpu costing is enabled.But what order are the commands being run? And why is the ANALYZE command being used to gather optimizer stats.
    In the first plan:
    INDEX FULL SCAN DESCENDING BMTEST IDX_MESSAGE_2 1 168
    Why this index full scan cost only 1? how did oracle get this number? Is there formula to caculate the cost of index full scan? I have read the article named "Cost Based Oracle Fundamentals" and there is no introduce how to caculate it.
    I think this abnormality cost makes the cost of next step "NESTED LOOPS" very smal and finally lead this abnormality result.1) Which article are you talking about? Are you talking about Jonathan Lewis's book "Cost Based Oracle Fundamentals"? Or are you referring to a different article somewhere?
    2) Can you post the query plans formatted via DBMS_XPLAN.DISPLAY (including the predicate information and enclose the output in the \[pre\] and \[pre\] tags to preserve white space?
    Justin
    Justin

  • Reg : Explain Plan -

    Hi Experts,
    I got a doubt regarding the Explain Plan.
    Is there any relation between the Cost shown in Explain Plan and the no of rows fetched by the query ?
    In other words - If the no of rows fetched by query increases, will that increase the cost also?
    Can anybody please provide me some pointers on this?
    Thanks & Regards,
    Ranit B.

    ranitB wrote:
    Hi Experts,
    I got a doubt regarding the Explain Plan.
    Is there any relation between the Cost shown in Explain Plan and the no of rows fetched by the query ?
    In other words - If the no of rows fetched by query increases, will that increase the cost also?
    Can anybody please provide me some pointers on this?The answer would be "not really" as the cost is single block read seek time from disk" . But if the number of rows which are expected+ to come in the result set are higher, the work done expected by Oracle would also be higher. So in an indirect way, the answer can be yes. That said, the number of rows which are shown in the explain plan (you should check the execution plan, explain plan is not the real plan) are the rows that the optimizer is expecting to fetch and the actual number ofrows fetched may or may not match with it.
    Aman....

  • Strange explain plan

    I wrote a SQL in Oracle EBS, please see the following:
    SELECT msi.segment1 item_num, mmt.revision revision,
    msi.description description_en,
    msi_tl.long_description description_cn,
    mmt.transfer_organization_id mfg_org_id,
    xxuts_inv_trh_pkg.get_organization_name(mmt.transfer_organization_id),
    mmt.subinventory_code subinv, mmt.locator_id,
    mtln.lot_number lot_num, mmt.transaction_id txn_id,
    mmt.transfer_subinventory co_subinv, mmt.transfer_locator_id,
    mmt.transaction_date txn_date, fn.user_name user_name,
    mts.transaction_source_type_name txn_source_type,
    wie.wip_entity_name order_num,
    xxuts_inv_trh_pkg.get_qty_before (mmt.organization_id,
    mmt.inventory_item_id,
    mmt.revision,
    mmt.subinventory_code,
    mmt.transaction_id,
    mmt.transaction_date
    DECODE (msi.lot_control_code,
    2, mtln.transaction_quantity,
    mmt.transaction_quantity
    ) txn_qty,
    mtt.transaction_type_name txn_type, mmt.actual_cost item_cost,
    DECODE (msi.lot_control_code,
    2, mtln.transaction_quantity,
    mmt.transaction_quantity
    * mmt.actual_cost amount,
    mtln.primary_quantity primary_qty,
    NVL
    (mtr.reason_name,
    (SELECT mtrh.attribute1 || mtrh.attribute2 || mtrh.attribute3
    FROM mtl_txn_request_headers mtrh
    WHERE EXISTS (
    SELECT 'X'
    FROM mtl_txn_request_lines mtrl
    WHERE mtrh.header_id = mtrl.header_id
    AND mtrl.transaction_header_id =
    mmt.transaction_set_id
    AND mtrl.txn_source_id = mmt.transaction_source_id
    AND mtrl.line_id = mmt.source_line_id))
    ) reason,
    mmt.transaction_reference REFERENCE
    FROM mtl_system_items_b msi --250,
    mtl_system_items_tl msi_tl --500,
    mtl_transaction_lot_numbers mtln -210,
    mtl_material_transactions mmt -333,
    mtl_transaction_types mtt,
    mtl_txn_source_types mts,
    mtl_item_categories mic -800,
    mtl_transaction_reasons mtr,
    fnd_user fn,
    wip_entities wie --5
    WHERE msi.inventory_item_id = mmt.inventory_item_id
    AND msi.inventory_item_id = msi_tl.inventory_item_id
    AND msi.organization_id = msi_tl.organization_id
    AND mtr.reason_id(+) = mmt.reason_id
    AND msi_tl.LANGUAGE = USERENV ('LANG')
    AND mmt.transaction_id = mtln.transaction_id(+)
    AND mic.inventory_item_id = mmt.inventory_item_id
    AND mic.organization_id = mmt.organization_id
    AND mic.category_set_id = :b15
    AND mmt.transaction_type_id = mtt.transaction_type_id
    AND mmt.transaction_source_type_id = mts.transaction_source_type_id
    AND msi.organization_id = mmt.organization_id
    AND mmt.transaction_source_id = wie.wip_entity_id
    AND mmt.transaction_source_type_id IN (5)
    AND fn.user_id = mmt.created_by
    AND mmt.organization_id = :b14
    AND msi.segment1 >= NVL (:b13, msi.segment1)
    AND msi.segment1 <= NVL (:b12, msi.segment1)
    AND NVL (mmt.revision, '-99') = NVL (NVL (:b11, mmt.revision), '-99')
    AND mmt.subinventory_code >= NVL (:b10, mmt.subinventory_code)
    AND mmt.subinventory_code <= NVL (:b9, mmt.subinventory_code)
    AND mmt.transaction_date BETWEEN :b8 AND :b7
    AND mmt.creation_date BETWEEN :b6 AND :b5
    AND mmt.transaction_type_id = NVL (:b4, mmt.transaction_type_id)
    AND mmt.transaction_source_type_id = NVL (:b3, mmt.transaction_source_type_id)
    AND mmt.transaction_id = NVL (:b2, mmt.transaction_id)
    AND fn.user_id = NVL (:b1, fn.user_id)
    It's explain plan is:
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | INSERT STATEMENT | | | | 33 (100)| |
    | 1 | CONCATENATION | | | | | |
    |* 2 | FILTER | | | | | |
    | 3 | NESTED LOOPS | | 1 | 312 | 17 (0)| 00:00:01 |
    | 4 | NESTED LOOPS | | 1 | 297 | 15 (0)| 00:00:01 |
    | 5 | NESTED LOOPS OUTER | | 1 | 282 | 13 (0)| 00:00:01 |
    | 6 | NESTED LOOPS | | 1 | 257 | 10 (0)| 00:00:01 |
    | 7 | NESTED LOOPS | | 1 | 188 | 8 (0)| 00:00:01 |
    | 8 | NESTED LOOPS | | 1 | 174 | 7 (0)| 00:00:01 |
    | 9 | NESTED LOOPS | | 1 | 148 | 6 (0)| 00:00:01 |
    | 10 | NESTED LOOPS OUTER | | 1 | 128 | 5 (0)| 00:00:01 |
    | 11 | NESTED LOOPS | | 1 | 108 | 4 (0)| 00:00:01 |
    | 12 | TABLE ACCESS BY INDEX ROWID| MTL_TXN_SOURCE_TYPES | 1 | 18 | 1 (0)| 00:00:01 |
    |* 13 | INDEX UNIQUE SCAN | MTL_TXN_SOURCE_TYPES_U1 | 1 | | 0 (0)| |
    |* 14 | TABLE ACCESS BY INDEX ROWID| MTL_MATERIAL_TRANSACTIONS | 1 | 90 | 3 (0)| 00:00:01 |
    |* 15 | INDEX RANGE SCAN | MTL_MATERIAL_TRANSACTIONS_N8 | 1 | | 2 (0)| 00:00:01 |
    | 16 | TABLE ACCESS BY INDEX ROWID | MTL_TRANSACTION_REASONS | 1 | 20 | 1 (0)| 00:00:01 |
    |* 17 | INDEX UNIQUE SCAN | MTL_TRANSACTION_REASONS_U1 | 1 | | 0 (0)| |
    | 18 | TABLE ACCESS BY INDEX ROWID | WIP_ENTITIES | 1 | 20 | 1 (0)| 00:00:01 |
    |* 19 | INDEX UNIQUE SCAN | WIP_ENTITIES_U1 | 1 | | 0 (0)| |
    | 20 | TABLE ACCESS BY INDEX ROWID | MTL_TRANSACTION_TYPES | 1 | 26 | 1 (0)| 00:00:01 |
    |* 21 | INDEX UNIQUE SCAN | MTL_TRANSACTION_TYPES_U1 | 1 | | 0 (0)| |
    | 22 | TABLE ACCESS BY INDEX ROWID | FND_USER | 1 | 14 | 1 (0)| 00:00:01 |
    |* 23 | INDEX UNIQUE SCAN | FND_USER_U1 | 1 | | 0 (0)| |
    |* 24 | TABLE ACCESS BY INDEX ROWID | MTL_SYSTEM_ITEMS_B | 1 | 69 | 2 (0)| 00:00:01 |
    |* 25 | INDEX UNIQUE SCAN | MTL_SYSTEM_ITEMS_B_U1 | 1 | | 1 (0)| 00:00:01 |
    | 26 | TABLE ACCESS BY INDEX ROWID | MTL_TRANSACTION_LOT_NUMBERS | 1 | 25 | 3 (0)| 00:00:01 |
    |* 27 | INDEX RANGE SCAN | MTL_TRANSACTION_LOT_NUMBERS_N1 | 1 | | 2 (0)| 00:00:01 |
    |* 28 | INDEX RANGE SCAN | MTL_ITEM_CATEGORIES_U1 | 1 | 15 | 2 (0)| 00:00:01 |
    | 29 | TABLE ACCESS BY INDEX ROWID | MTL_SYSTEM_ITEMS_TL | 1 | 15 | 2 (0)| 00:00:01 |
    |* 30 | INDEX UNIQUE SCAN | MTL_SYSTEM_ITEMS_TL_U1 | 1 | | 1 (0)| 00:00:01 |
    |* 31 | FILTER | | | | | |
    | 32 | NESTED LOOPS OUTER | | 1 | 312 | 16 (0)| 00:00:01 |
    | 33 | NESTED LOOPS | | 1 | 287 | 13 (0)| 00:00:01 |
    | 34 | NESTED LOOPS | | 1 | 272 | 11 (0)| 00:00:01 |
    | 35 | NESTED LOOPS | | 1 | 257 | 9 (0)| 00:00:01 |
    | 36 | NESTED LOOPS | | 1 | 188 | 7 (0)| 00:00:01 |
    | 37 | NESTED LOOPS OUTER | | 1 | 162 | 6 (0)| 00:00:01 |
    | 38 | NESTED LOOPS | | 1 | 142 | 5 (0)| 00:00:01 |
    | 39 | NESTED LOOPS | | 1 | 128 | 4 (0)| 00:00:01 |
    | 40 | NESTED LOOPS | | 1 | 108 | 3 (0)| 00:00:01 |
    | 41 | TABLE ACCESS BY INDEX ROWID| MTL_TXN_SOURCE_TYPES | 1 | 18 | 1 (0)| 00:00:01 |
    |* 42 | INDEX UNIQUE SCAN | MTL_TXN_SOURCE_TYPES_U1 | 1 | | 0 (0)| |
    |* 43 | TABLE ACCESS BY INDEX ROWID| MTL_MATERIAL_TRANSACTIONS | 1 | 90 | 2 (0)| 00:00:01 |
    |* 44 | INDEX UNIQUE SCAN | MTL_MATERIAL_TRANSACTIONS_U1 | 1 | | 1 (0)| 00:00:01 |
    | 45 | TABLE ACCESS BY INDEX ROWID | WIP_ENTITIES | 48143 | 940K| 1 (0)| 00:00:01 |
    |* 46 | INDEX UNIQUE SCAN | WIP_ENTITIES_U1 | 1 | | 0 (0)| |
    | 47 | TABLE ACCESS BY INDEX ROWID | FND_USER | 1 | 14 | 1 (0)| 00:00:01 |
    |* 48 | INDEX UNIQUE SCAN | FND_USER_U1 | 1 | | 0 (0)| |
    | 49 | TABLE ACCESS BY INDEX ROWID | MTL_TRANSACTION_REASONS | 36 | 720 | 1 (0)| 00:00:01 |
    |* 50 | INDEX UNIQUE SCAN | MTL_TRANSACTION_REASONS_U1 | 1 | | 0 (0)| |
    | 51 | TABLE ACCESS BY INDEX ROWID | MTL_TRANSACTION_TYPES | 98 | 2548 | 1 (0)| 00:00:01 |
    |* 52 | INDEX UNIQUE SCAN | MTL_TRANSACTION_TYPES_U1 | 1 | | 0 (0)| |
    |* 53 | TABLE ACCESS BY INDEX ROWID | MTL_SYSTEM_ITEMS_B | 297 | 20493 | 2 (0)| 00:00:01 |
    |* 54 | INDEX UNIQUE SCAN | MTL_SYSTEM_ITEMS_B_U1 | 1 | | 1 (0)| 00:00:01 |
    | 55 | TABLE ACCESS BY INDEX ROWID | MTL_SYSTEM_ITEMS_TL | 96026 | 1406K| 2 (0)| 00:00:01 |
    |* 56 | INDEX UNIQUE SCAN | MTL_SYSTEM_ITEMS_TL_U1 | 1 | | 1 (0)| 00:00:01 |
    |* 57 | INDEX RANGE SCAN | MTL_ITEM_CATEGORIES_U1 | 1 | 15 | 2 (0)| 00:00:01 |
    | 58 | TABLE ACCESS BY INDEX ROWID | MTL_TRANSACTION_LOT_NUMBERS | 1 | 25 | 3 (0)| 00:00:01 |
    |* 59 | INDEX RANGE SCAN | MTL_TRANSACTION_LOT_NUMBERS_N1 | 1 | | 2 (0)| 00:00:01 |
    Predicate Information (identified by operation id):
    2 - filter((:B6<=:B5 AND :B8<=:B7 AND :B2 IS NULL))
    13 - access("MTS"."TRANSACTION_SOURCE_TYPE_ID"=5)
    14 - filter(("MMT"."TRANSACTION_SOURCE_ID" IS NOT NULL AND
    "MMT"."TRANSACTION_TYPE_ID"=NVL(:B4,"MMT"."TRANSACTION_TYPE_ID") AND
    "MMT"."SUBINVENTORY_CODE">=NVL(:B10,"MMT"."SUBINVENTORY_CODE") AND
    "MMT"."SUBINVENTORY_CODE"<=NVL(:B9,"MMT"."SUBINVENTORY_CODE") AND
    NVL("MMT"."REVISION",'-99')=NVL(NVL(:B11,"MMT"."REVISION"),'-99') AND "MMT"."TRANSACTION_ID" IS NOT NULL AND
    "MMT"."CREATION_DATE">=:B6 AND "MMT"."CREATION_DATE"<=:B5))
    15 - access("MMT"."TRANSACTION_SOURCE_TYPE_ID"=5 AND "MMT"."ORGANIZATION_ID"=:B14 AND
    "MMT"."TRANSACTION_DATE">=:B8 AND "MMT"."TRANSACTION_DATE"<=:B7)
    filter(NVL(:B3,"MMT"."TRANSACTION_SOURCE_TYPE_ID")=5)
    17 - access("MTR"."REASON_ID"="MMT"."REASON_ID")
    19 - access("MMT"."TRANSACTION_SOURCE_ID"="WIE"."WIP_ENTITY_ID")
    21 - access("MMT"."TRANSACTION_TYPE_ID"="MTT"."TRANSACTION_TYPE_ID")
    23 - access("FN"."USER_ID"="MMT"."CREATED_BY")
    filter("FN"."USER_ID"=NVL(:B1,"FN"."USER_ID"))
    24 - filter(("MSI"."SEGMENT1">=NVL(:B13,"MSI"."SEGMENT1") AND "MSI"."SEGMENT1"<=NVL(:B12,"MSI"."SEGMENT1")))
    25 - access("MSI"."INVENTORY_ITEM_ID"="MMT"."INVENTORY_ITEM_ID" AND "MSI"."ORGANIZATION_ID"=:B14)
    27 - access("MMT"."TRANSACTION_ID"="MTLN"."TRANSACTION_ID")
    28 - access("MIC"."ORGANIZATION_ID"=:B14 AND "MIC"."INVENTORY_ITEM_ID"="MMT"."INVENTORY_ITEM_ID" AND
    "MIC"."CATEGORY_SET_ID"=:B15)
    30 - access("MSI"."INVENTORY_ITEM_ID"="MSI_TL"."INVENTORY_ITEM_ID" AND "MSI_TL"."ORGANIZATION_ID"=:B14 AND
    "MSI_TL"."LANGUAGE"=USERENV('LANG'))
    31 - filter((:B6<=:B5 AND :B8<=:B7 AND :B2 IS NOT NULL))
    42 - access("MTS"."TRANSACTION_SOURCE_TYPE_ID"=5)
    43 - filter(("MMT"."TRANSACTION_SOURCE_ID" IS NOT NULL AND "MMT"."TRANSACTION_DATE">=:B8 AND
    "MMT"."ORGANIZATION_ID"=:B14 AND "MMT"."TRANSACTION_SOURCE_TYPE_ID"=5 AND
    NVL(:B3,"MMT"."TRANSACTION_SOURCE_TYPE_ID")=5 AND "MMT"."TRANSACTION_TYPE_ID"=NVL(:B4,"MMT"."TRANSACTION_TYPE_ID"
    ) AND "MMT"."SUBINVENTORY_CODE">=NVL(:B10,"MMT"."SUBINVENTORY_CODE") AND
    "MMT"."SUBINVENTORY_CODE"<=NVL(:B9,"MMT"."SUBINVENTORY_CODE") AND
    NVL("MMT"."REVISION",'-99')=NVL(NVL(:B11,"MMT"."REVISION"),'-99') AND "MMT"."TRANSACTION_DATE"<=:B7 AND
    "MMT"."CREATION_DATE">=:B6 AND "MMT"."CREATION_DATE"<=:B5))
    44 - access("MMT"."TRANSACTION_ID"=:B2)
    46 - access("MMT"."TRANSACTION_SOURCE_ID"="WIE"."WIP_ENTITY_ID")
    48 - access("FN"."USER_ID"="MMT"."CREATED_BY")
    filter("FN"."USER_ID"=NVL(:B1,"FN"."USER_ID"))
    50 - access("MTR"."REASON_ID"="MMT"."REASON_ID")
    52 - access("MMT"."TRANSACTION_TYPE_ID"="MTT"."TRANSACTION_TYPE_ID")
    53 - filter(("MSI"."SEGMENT1">=NVL(:B13,"MSI"."SEGMENT1") AND "MSI"."SEGMENT1"<=NVL(:B12,"MSI"."SEGMENT1")))
    54 - access("MSI"."INVENTORY_ITEM_ID"="MMT"."INVENTORY_ITEM_ID" AND "MSI"."ORGANIZATION_ID"=:B14)
    56 - access("MSI"."INVENTORY_ITEM_ID"="MSI_TL"."INVENTORY_ITEM_ID" AND "MSI_TL"."ORGANIZATION_ID"=:B14 AND
    "MSI_TL"."LANGUAGE"=USERENV('LANG'))
    57 - access("MIC"."ORGANIZATION_ID"=:B14 AND "MIC"."INVENTORY_ITEM_ID"="MMT"."INVENTORY_ITEM_ID" AND
    "MIC"."CATEGORY_SET_ID"=:B15)
    59 - access("MMT"."TRANSACTION_ID"="MTLN"."TRANSACTION_ID")
    I am doubt why to perform two times explain plan(Predicate -2 and 31).
    Thanks

    Tom.lai wrote:
    I wrote a SQL in Oracle EBS, please see the following:
    AND msi.segment1 >= NVL (:b13, msi.segment1)
    AND msi.segment1 <= NVL (:b12, msi.segment1)
    AND NVL (mmt.revision, '-99') = NVL (NVL (:b11, mmt.revision), '-99')
    AND mmt.subinventory_code >= NVL (:b10, mmt.subinventory_code)
    AND mmt.subinventory_code <= NVL (:b9, mmt.subinventory_code)
    AND mmt.transaction_date BETWEEN :b8 AND :b7
    AND mmt.creation_date BETWEEN :b6 AND :b5
    AND mmt.transaction_type_id = NVL (:b4, mmt.transaction_type_id)
    AND mmt.transaction_source_type_id = NVL (:b3, mmt.transaction_source_type_id)
    AND mmt.transaction_id = NVL (:b2, mmt.transaction_id)
    AND fn.user_id = NVL (:b1, fn.user_id)I am doubt why to perform two times explain plan(Predicate -2 and 31).Using your NVL expressions above you've hit a special implementation for this particular construct in the Oracle optimizer, for more information, see here:
    http://jonathanlewis.wordpress.com/2007/01/09/conditional-sql/
    http://jonathanlewis.wordpress.com/2007/02/14/conditional-sql-2/
    This splits your plan into two plans for the two cases possible, and depending on if the value passed is NULL or not only one of the branches will actually get executed.
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/

  • Query tunning in Oracle using Explain Plan

    Adding to my below question: I have now modified the query and the path shownby 'Explain plan' has reduced. The 'Time' column of plan_table is also showing much lesser value. However, some people are suggesting me to consider the time required by the query to execute on Toad. Will it be practical? Please help!!
    Hi, I am using Oracle 11g. I need to optimize a Select query(Need to minimize the execution time). I need to know how 'Explain Plan' would help me. I know how to use Explain Plan command. I refer Plan_table table to see the details of the plan. Please guide me regarding which columns of the Plan_table should be considered while modifying the query for optimization. Some people say, 'Time' column should be considered, some say 'Bytes' etc. Some suggest on minimizing the full table scans, while some people say that I should minimize the total no. operations (less no. of rows should be displayed in Plan_table). As per an experienced friend of mine, full table scans should be reduced (for e.g. if there are 5 full table scans in the plan, then try to reduce them to less than 5. ). However, if I consider any full table scan operation in the plan_table, its shows value of 'time' column as only 1 which is very very less. Does this mean the full scan is actually taking very less time?? If yes, then this means full table scans are very fast in my case and no need to work on them. Some articles suggest that plan shown by 'Explain Plan' command is not necessarily followed while executing the query. So what should I look for then? How should I optimize the query and how will I come to know that it's optimized?? Please help!!...
    Edited by: 885901 on Sep 20, 2011 2:10 AM

    885901 wrote:
    Hi, I am using Oracle 11g. I need to optimize a Select query(Need to minimize the execution time). I need to know how 'Explain Plan' would help me. I know how to use Explain Plan command. I refer Plan_table table to see the details of the plan. Please guide me regarding which columns of the Plan_table should be considered while modifying the query for optimization. Some people say, 'Time' column should be considered, some say 'Bytes' etc. Some suggest on minimizing the full table scans, while some people say that I should minimize the total no. operations (less no. of rows should be displayed in Plan_table). As per an experienced friend of mine, full table scans should be reduced (for e.g. if there are 5 full table scans in the plan, then try to reduce them to less than 5. ). However, if I consider any full table scan operation in the plan_table, its shows value of 'time' column as only 1 which is very very less. Does this mean the full scan is actually taking very less time?? If yes, then this means full table scans are very fast in my case and no need to work on them. Some articles suggest that plan shown by 'Explain Plan' command is not necessarily followed while executing the query. So what should I look for then? How should I optimize the query and how will I come to know that it's optimized?? Please help!!...how fast is fast enough?

  • Problems with explain plan and statement

    Hi community,
    I have migrated a j2ee application from DB2 to Oracle.
    First some facts of our application and database instance:
    We are using oracle version 10.2.0.3 and driver version 10.2.0.3. It runs with charset Unicode 3.0 UTF-8.
    Our application is using Tomcat as web container and jboss as application server. We are only using prepared statements. So if I talk about statements I always mean prepared statements. Also our application is setting the defaultNChar property to true because every char and varchar field has been created as an nchar and nvarchar.
    We have some jsp sites that contains lists with search forms. Everytime I enter a value to the form that returns a filled resultset, the lists are performing great. But everytime I enter a value that returns an empty resultset, the lists are 100 times slower. The jsp sites are running in the tomcat environment and submitting their statements directly to the database. The connections are pooled by dbcp. So what can cause this behaviour??
    To anaylze this problem I started logging all statements and filled-in search field values and combinations that are executed by the lists described above. I also developed a standalone helper tool that reads the logged statements, executes them to the database and generates an explain plan for every statement. But now there appears a strange situation. Every statement, that performs really fast within our application, is now executed by the helper tool extremely slow. So I edited some jsp pages within our application to force an explain plan from there (tomcat env). So when I'm executing the same statement I'm getting with the exactly same code two completely different explain plans.
    First the statement itself:
    select LINVIN.BBASE , INVINNUM , INVINNUMALT , LINVIN.LSUPPLIERNUM , LSUPPLIERNUMEXT , LINVIN.COMPANYCODE , ACCOUNT , INVINTXT , INVINSTS , INVINTYP , INVINDAT , RECEIPTDAT , POSTED , POSTINGDATE , CHECKCOSTCENTER , WORKFLOWIDEXT , INVINREFERENCE , RESPONSIBLEPERS , INVINSUM_V , INVINSUMGROSS_V , VOUCHERNUM , HASPOSITIONS , PROCESSINSTANCEID , FCURISO_V , LSUPPLIER.AADDRLINE1 from LINVIN, LSUPPLIER where LINVIN.BBASE = LSUPPLIER.BBASE and LINVIN.LSUPPLIERNUM = LSUPPLIER.LSUPPLIERNUM and LINVIN.BBASE = ? order by LINVIN.BBASE, INVINDAT DESC
    Now the explain plan from our application:
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 101 | 28583 | 55 (0)| 00:00:01 |
    | 1 | NESTED LOOPS | | 101 | 28583 | 55 (0)| 00:00:01 |
    | 2 | TABLE ACCESS BY INDEX ROWID| LINVIN | 93709 | 12M| 25 (0)| 00:00:01 |
    |* 3 | INDEX RANGE SCAN | LINV_INVDAT | 101 | | 1 (0)| 00:00:01 |
    | 4 | TABLE ACCESS BY INDEX ROWID| LSUPPLIER | 1 | 148 | 1 (0)| 00:00:01 |
    |* 5 | INDEX UNIQUE SCAN | PK_177597 | 1 | | 1 (0)| 00:00:01 |
    Predicate Information (identified by operation id):
    3 - access("LINVIN"."BBASE"=:1)
    filter("LINVIN"."BBASE"=:1)
    5 - access("LSUPPLIER"."BBASE"=:1 AND "LINVIN"."LSUPPLIERNUM"="LSUPPLIER"."LSUPPLIERNUM")
    Now the one from the standalone tool:
    | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 93773 | 25M| | 12898 (1)| 00:02:35 |
    | 1 | SORT ORDER BY | | 93773 | 25M| 61M| 12898 (1)| 00:02:35 |
    |* 2 | HASH JOIN | | 93773 | 25M| 2592K| 7185 (1)| 00:01:27 |
    | 3 | TABLE ACCESS BY INDEX ROWID| LSUPPLIER | 16540 | 2390K| | 332 (0)| 00:00:04 |
    |* 4 | INDEX RANGE SCAN | LSUPPLIER_HAS_BASE_FK | 16540 | | | 11 (0)| 00:00:01 |
    | 5 | TABLE ACCESS BY INDEX ROWID| LINVIN | 93709 | 12M| | 6073 (1)| 00:01:13 |
    |* 6 | INDEX RANGE SCAN | LINVOICE_BMDT_FK | 93709 | | | 84 (2)| 00:00:02 |
    Predicate Information (identified by operation id):
    2 - access("LINVIN"."BBASE"="LSUPPLIER"."BBASE" AND "LINVIN"."LSUPPLIERNUM"="LSUPPLIER"."LSUPPLIERNUM")
    4 - access("LSUPPLIER"."BBASE"=:1)
    6 - access("LINVIN"."BBASE"=:1)
    The size of the tables are: LINVIN - 383.692 Rows, LSUPPLIER - 115.782 Rows
    As you can see the one executed from our application is much faster than the one from the helper tool. So why picks oracle a completely different explain plan for the same statement? An why is a hash join much slower than a nested loop? Because If I'm right a nested loop should only be used when the tables are pretty small..
    I also tried to play with some parameters:
    I set optimizer_index_caching to 100 and optimizer_index_cost_adj to 30. I also changed optimizer_mode to FIRST_ROWS_100.
    I would really appreciated, if somebody can help me with this issue, because I'm really getting more and more distressed...
    Thanks in advance,
    Tobias
    Edited by: tobiwan on Sep 3, 2008 11:49 PM
    Edited by: tobiwan on Sep 3, 2008 11:50 PM
    Edited by: tobiwan on Sep 4, 2008 12:01 AM
    Edited by: tobiwan on Sep 4, 2008 12:02 AM
    Edited by: tobiwan on Sep 4, 2008 12:04 AM
    Edited by: tobiwan on Sep 4, 2008 12:06 AM
    Edited by: tobiwan on Sep 4, 2008 12:06 AM
    Edited by: tobiwan on Sep 4, 2008 12:07 AM

    tobiwan wrote:
    Hi again,
    Here ist the answer:
    The problem, because I got two different explain plans, was that the external tool uses the NLS sesssion parameters coming from the OS which are in my case "de/DE".
    Within our application these parameters are changed to "en/US"!! So if I'm calling in my external tool the java function Locale.setDefault(new Locale("en","US")) before connecting to the database the explain plans are finally equal.That might explain why you got two different execution plan, because one plan was obviously able to avoid a SORT ORDER BY operation, whereas the second plan required to run SORT ORDER BY operation, obviously because of the different NLS_SORT settings. An index by default uses the NLS_SORT = 'binary' order whereas ORDER BY obeys the NLS_SORT setting, which probably was set to 'GERMAN' in your "external tool" case. You can check the "NLS_SESSION_PARAMETERS" view to check your current NLS_SORT setting.
    For more information regarding this issue, see my blog note I've written about this some time ago:
    http://oracle-randolf.blogspot.com/2008/09/getting-first-rows-of-large-sorted.html
    Now let me make a guess why you observe the behaviour that it takes so long if your result set is empty:
    The plan avoiding the SORT ORDER BY is able to return the first rows of the result set very quickly, but could take quite a while until all rows are processed, since it requires potentially a lot of iterations of the loop until everything has been processed. Your front end probably by default only display the first n rows of the result set and therefore works fine with this execution plan.
    Now if the result set is empty, depending on your data, indexes and search criteria, Oracle has to work through all the data using the inefficient NESTED LOOP approach only to find out that no data has been found, and since your application attempts to fetch the first n records, but no records will be found, it has to wait until all data has been processed.
    You can try to reproduce this by deliberately fetching all records of a query that returns data and that uses the NESTED LOOP approach... It probably takes as long as in the case when no records are found.
    Note that you seem to use bind variables and 10g, therefore you might be interested that due to the "bind variable peeking" functionality you might potentially end up with "unstable" plans depending on the values "peeked" when the statement is parsed.
    For more information, see this comprehensive description of the issue:
    http://www.pythian.com/blogs/867/stabilize-oracle-10gs-bind-peeking-behaviour-by-cutting-histograms
    Note that this changes in 11g with the introduction of the "Adaptive Cursor Sharing".
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/

  • Cpu time is not getting displayed in explain plan

    Hi All,
    I am trying to analyze one query using explain plan .like below
    1) explain plan for
    SELECT /*+ parallel(tsp,8) use_hash( tsp tp) */ count(1)
    FROM router tp,
    receiver tsp
    WHERE tp.rs = tsp.rp
    AND creater_date >=to_date('04032009000000','ddmmyyyyhh24miss')
    and tsp.XVF is not null
    and tp.XVF is not null
    and tp.role_name='BR';
    2)@$ORACLE_HOME/rdbms/admin/utlxpls.sql
    But i am getting only following columns in result .
    | Id | Operation | Name | Rows | Bytes | Cost |
    No Cpu time preset .
    How can i extimate CPU time ?
    Pls help
    Thanks

    am_73798 wrote:
    I am trying to analyze one query using explain plan .like below
    But i am getting only following columns in result .
    | Id | Operation | Name | Rows | Bytes | Cost |
    No Cpu time preset .
    How can i extimate CPU time ?You need to mention your database version (4-digits, e.g. 9.2.0.8).
    In Oracle 9i CPU costing is disabled by default, you need to gather WORKLOAD system statistics to enable the CPU costing.
    In 10g CPU costing is enabled by default and uses default NOWORKLOAD system statistics if no WORKLOAD system statistics have been gathered. It can only be disabled by setting an undocumented parameter or by changing the OPTIMIZER_FEATURES_ENABLE parameter back to 9i compatibility.
    You can check the status of your system statistics by running the following query in SQL*Plus:
    column sname format a20
    column pname format a20
    column pval2 format a20
    select
    sname
    , pname
    , pval1
    , pval2
    from
    sys.aux_stats$;Can you show us the actual (complete) output you get from "utlxpls.sql"? Use the \ tag to preserve formatting here:
    \output
    \will show asoutput
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

  • Not Understanding the filter in Explain Plan - filter(NULL IS NOT NULL)

    Hi All,
    Request your help in understanding the below scenario. (I am not aware of teh application and table details. Just trying to help my friend)
    SQL> conn
    Enter user-name: [email protected]
    Enter password:
    Connected.
    SQL> select * from v$version;
    BANNER
    Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
    PL/SQL Release 10.2.0.3.0 - Production
    CORE    10.2.0.3.0      Production
    TNS for Linux: Version 10.2.0.3.0 - Production
    NLSRTL Version 10.2.0.3.0 - Production
    --Checking the count in PO_LINES
    SQL> select count(*) from po_lines;
      COUNT(*)
             0
    --PO_LINES is a synonym
    SQL> select object_type,owner from dba_objects where object_name = 'PO_LINES';
    OBJECT_TYPE         OWNER
    SYNONYM             APPS
    --The synonym is pointing to PO.PO_LINES_ALL
    SQL> select * from user_synonyms where synonym_name = 'PO_LINES';
    SYNONYM_NAME                   TABLE_OWNER                    TABLE_NAME                     DB_LINK
    PO_LINES                       PO                             PO_LINES_ALL
    --But when counting PO.PO_LINES_ALL I am getting different result
    SQL> select count(*) c from po.po_lines_all;
             C
          8828
    --Explain plan of teh original query is
    SQL> explain plan for
      2  select
      3  * from po_lines;
    Explained.
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    | Id  | Operation          | Name         | Rows  | Bytes | Cost (%CPU)|
    |   0 | SELECT STATEMENT   |              |     1 |   252 |     0   (0)|
    |*  1 |  FILTER            |              |       |       |            |
    |   2 |   TABLE ACCESS FULL| PO_LINES_ALL |  8796 |  2164K|   106   (4)|
    Predicate Information (identified by operation id):
       1 - filter(NULL IS NOT NULL)
    --Now the object PO.PO_LINES_ALL is TABLE, not an mview.
    SQL> select object_type,owner from dba_objects where object_name = 'PO_LINES_ALL';
    OBJECT_TYPE         OWNER
    TABLE               POSeek your help in understanding what is happening here.
    Thanks in Advance,
    jeneesh

    Next time, prefix with APPS. when you show us the explain plan:
    SQL> explain plan for
      2  select
      3  * from apps.po_lines;  -- added the prefix of owner.Just like you prefixed with PO. when you showed us the query on PO_LINES_ALL. It ensures that you are using the synonym which you showed us.
    Btw. PO_LINES_ALL, could still be a VIEW given your overview of the situation.
    Anyway a filter "NULL IS NOT NULL" is indicative that the optimizer performed something called semantic query optimization (SQO).
    SQO is the process of deducing new predicates based upon a) existing predicates in your query (which there is none), b) added predicates to your query (eg. by a VPD policy function), and c) declared constraints on the tables invovled in your query.
    A typical example of when a "NOT is NOT NULL" predicate will show up is when for instance in the EMP table there is a declared constraint on EMPNO like this:
    check(EMPNO > 0)And your query would hold a predicate that is inconsistent with the constraint, for instance like this:
    select *
    from EMP
    where EMPNO <= 0Oracle will deduce that EMPNO cannot be both greater than zero (constraint) as well as smaller than or equal to zero (your query predicate), and will transform the query into:
    select *
    from EMP
    where EMPNO <= 0
      and NULL is NOT NULLThus preventing accessing the EMP table all together, and immediately returning this query with no data found.
    Edited by: Toon Koppelaars on Mar 15, 2010 7:17 AM

  • Filter(NULL IS NOT NULL) in Explain Plan ??

    Hi All,
    Can someone please explain what this explain plan statement means? I see a filter(NULL IS NOT NULL) as the first statement - could not figure out why it came up so from googling.
    My Query Used:
    EXPLAIN PLAN FOR
    MERGE INTO summary_bysrccd
    USING
    (SELECT LAST_DAY(TRUNC(to_timestamp(os.requestdatetime, 'yyyymmddhh24:mi:ss.ff4'))) AS SUMMARY_DATE,
    os.acctnum,
    ol.sourcecode AS sourcecode,
    ol.sourcename AS sourcename,
    count(1) cnt_articleview
    FROM article_views os , master_sourcecode ol
    where os.sourcecode = ol.sourcecode
    AND os.acctnum IS NOT NULL
    AND ol.sourcecode IS NOT NULL
    AND os.requestdatetime IS NOT NULL
    AND UPPER(os.success_ind) = 'S'
         AND (
              ('INCR'  = 'FULL'
              AND  (get_date_timestamp(os.requestdatetime) BETWEEN TO_DATE('23-AUG-2011 00:00:00','DD-MON-YYYY HH24:MI:SS') AND TO_DATE('27-AUG-2011 23:59:59','DD-MON-YYYY HH24:MI:SS')
              AND   os.entry_CreatedDate BETWEEN TO_DATE('22-AUG-2011 00:00:00','DD-MON-YYYY HH24:MI:SS') AND TO_DATE('28-AUG-2011 00:00:00','DD-MON-YYYY HH24:MI:SS')
              OR ('INCR' = 'FULL'
              AND os.entry_createddate BETWEEN TO_DATE('23-AUG-2011 00:00:00','DD-MON-YYYY HH24:MI:SS') AND TO_DATE('27-AUG-2011 23:59:59','DD-MON-YYYY HH24:MI:SS') )
    group by LAST_DAY(TRUNC(to_timestamp(os.requestdatetime, 'yyyymmddhh24:mi:ss.ff4'))),
    os.acctnum,ol.sourcecode,ol.sourcename) mrg_query
    ON (ods_av_summary_bysrccd.acctnum = mrg_query.acctnum AND
    ods_av_summary_bysrccd.summary_date=mrg_query.summary_date AND
    ods_av_summary_bysrccd.sourcecode=mrg_query.sourcecode)
    WHEN NOT MATCHED THEN
    INSERT (SUMMARY_date,ACCTNUM,SOURCECODE,SOURCENAME,CNT_ARTICLEVIEW,ENTRY_LASTUPDATEDDATE)
    VALUES(mrg_query.summary_date,mrg_query.acctnum,mrg_query.sourcecode,mrg_query.sourcename,
    mrg_query.cnt_articleview,sysdate)
    WHEN MATCHED THEN
    UPDATE SET ods_av_summary_bysrccd.cnt_articleview=
    CASE WHEN NVL('INCR','INCR') = 'FULL' THEN mrg_query.cnt_articleview
    ELSE ods_av_summary_bysrccd.cnt_articleview+mrg_query.cnt_articleview
    END,
    ods_av_summary_bysrccd.entry_lastupdateddate=sysdate;My Explain Plan:
    SQL> select * from table(dbms_xplan.display);
    PLAN_TABLE_OUTPUT
    Plan hash value: 268591246
    | Id  | Operation                                 | Name                      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | MERGE STATEMENT                           |                           |     1 |   456 |       |     3   (0)| 00:00:01 |       |       |
    |   1 |  MERGE                                    | ODS_AV_SUMMARY_BYSRCCD    |       |       |       |            |          |       |       |
    |   2 |   VIEW                                    |                           |       |       |       |            |          |       |       |
    |   3 |    NESTED LOOPS OUTER                     |                           |     1 |   417 |       |     3   (0)| 00:00:01 |       |       |
    |   4 |     VIEW                                  |                           |     1 |   360 |       |     5 (100)| 00:00:01 |       |       |
    |   5 |      SORT GROUP BY                        |                           |     1 |    73 |   595M|            |          |       |       |
    PLAN_TABLE_OUTPUT
    |*  6 |       FILTER                              |                           |       |       |       |            |          |       |       |
    |*  7 |        HASH JOIN                          |                           |  6975K|   485M|  3944K| 17594   (1)| 00:03:32 |       |       |
    |   8 |         TABLE ACCESS FULL                 | ODS_MASTER_SOURCECODE     | 84021 |  2953K|       |   273   (1)| 00:00:04 |       |       |
    |*  9 |         TABLE ACCESS BY GLOBAL INDEX ROWID| ODS_ARTICLE_VIEWS         |  7007K|   247M|       |   826   (0)| 00:00:10 |    33 |    33 |
    |* 10 |          INDEX FULL SCAN                  | IDX_AV_ACCTNUM            |    25M|       |       |    26   (0)| 00:00:01 |       |       |
    |  11 |     TABLE ACCESS BY GLOBAL INDEX ROWID    | ODS_AV_SUMMARY_BYSRCCD    |     1 |    57 |       |     3   (0)| 00:00:01 | ROWID | ROWID |
    |* 12 |      INDEX UNIQUE SCAN                    | ODS_AV_SUMMARY_BYSRCCD_PK |     1 |       |       |     2   (0)| 00:00:01 |       |       |
    Predicate Information (identified by operation id):
    PLAN_TABLE_OUTPUT
       6 - filter(NULL IS NOT NULL)
       7 - access("OS"."SOURCECODE"="OL"."SOURCECODE")
       9 - filter("OS"."REQUESTDATETIME" IS NOT NULL AND "OS"."ENTRY_CREATEDDATE">=TO_DATE(' 2011-08-23 00:00:00', 'syyyy-mm-dd
                  hh24:mi:ss') AND "OS"."ENTRY_CREATEDDATE"<=TO_DATE(' 2011-08-27 23:59:59', 'syyyy-mm-dd hh24:mi:ss') AND UPPER("OS"."SUCCESS_IND")='S')
      10 - filter("OS"."ACCTNUM" IS NOT NULL)
      12 - access("ODS_AV_SUMMARY_BYSRCCD"."SUMMARY_DATE"(+)=INTERNAL_FUNCTION("MRG_QUERY"."SUMMARY_DATE") AND
                  "ODS_AV_SUMMARY_BYSRCCD"."ACCTNUM"(+)="MRG_QUERY"."ACCTNUM" AND "ODS_AV_SUMMARY_BYSRCCD"."SOURCECODE"(+)="MRG_QUERY"."SOURCECODE")
    Note
    PLAN_TABLE_OUTPUT
       - dynamic sampling used for this statement

    Hi Toon,
    Thanks for the quick resolution. I went back and verified the table's colunm details and it has a NOT NULL constraint.
    Regards,
    Chaitanya
    P.S: Is it ok if I ask you for some help regarding a production issue I have been encountering since 15 days but haev no clear resolution yet about what/why is the reason (the said issue is neither uniform nor regular - its affecting some modules and happening on some days - i shall give the full details if you are willing to have a look) - i shall start a new post or email you directly - yur convenience.

  • Explain plan results are different in SQL Developer than SQL Plus

    My Environment:
    SQL Developer 1.0.0.15.27
    Platform where SQL Developer is running: Windows XP 2002 SP2
    Oracle Database and Client 9.2.0.7
    Optimizer_mode: FIRST_ROWS
    I have the following SQL statement:
    SELECT a1.comp_id
    FROM temp_au_company a0, au_company a1
    WHERE :b2 = a0.temp_emp_code
    AND a0.comp_id = a1.comp_id
    AND a0.sls_terr_code != a1.sls_terr_code
    AND a1.last_mdfy_date > :b1
    When I run an Explain in SQL Developer I get the following access path (which is the one I really want):
    SELECT STATEMENT                          TABLE ACCESS(BY INDEX ROWID) FEDLINK.AU_COMPANY          NESTED LOOPS                                   INDEX(RANGE SCAN)
    FEDLINK.UX2_TEMP_AU_COMPANY
              INDEX(RANGE SCAN) FEDLINK.PX1_COMPANY
    However, when I execute the statement with sql_trace turned on and use tkprof to generate the actual access path, the statement executes as follows (which is WAY more expensive):
    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 3.58 6.68 28136 29232 0 0
    total 3 3.58 6.69 28136 29232 0 0
    Misses in library cache during parse: 1
    Optimizer goal: FIRST_ROWS
    Parsing user id: 979 (FEDLINK) (recursive depth: 1)
    Rows Row Source Operation
    0 NESTED LOOPS
    0 TABLE ACCESS FULL AU_COMPANY
    0 INDEX RANGE SCAN UX2_TEMP_AU_COMPANY (object id 49783)
    Notice the FULL access of au_company.
    I understand that SQL Developer has nothing to do with why the statement executed the way it did, but why is the Explain in SQL Developer different than the actual execution plan?
    Added note....when I run the explain in SQL Plus it is the same as the actual execution. Here is the explain from SQL Plus:
    explain plan for SELECT a1.comp_id
    FROM temp_au_company a0, au_company a1
    WHERE '1' = a0.temp_emp_code
    AND a0.comp_id = a1.comp_id
    AND a0.sls_terr_code != a1.sls_terr_code
    AND a1.last_mdfy_date > '01-MAY-2006';
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 2 | 76 | 2597 |
    | 1 | NESTED LOOPS | | 2 | 76 | 2597 |
    | 2 | TABLE ACCESS FULL | AU_COMPANY | 2 | 42 | 2595 |
    | 3 | INDEX RANGE SCAN | UX2_TEMP_AU_COMPANY | 1 | 17 | 2
    Thanks,
    Brenda

    The explain is different (full scan of au_company in SQL Plus / index access in SQL Developer) even when I use variables in SQL Plus. Here is the output for SQL Plus using variables instead of literals:
    SQL> variable b1 varchar2
    SQL> variable b2 char
    SQL> explain plan for SELECT a1.comp_id
    2 FROM temp_au_company a0, au_company a1
    3 WHERE :b2 = a0.temp_emp_code
    4 AND a0.comp_id = a1.comp_id
    5 AND a0.sls_terr_code != a1.sls_terr_code
    6 AND a1.last_mdfy_date > :b1
    7 /
    Explained.
    PLAN_TABLE_OUTPUT
    | Id | Operation | Name | Rows | Bytes | Cost |
    | 0 | SELECT STATEMENT | | 3184 | 118K| 2995 |
    | 1 | HASH JOIN | | 3184 | 118K| 2995 |
    | 2 | INDEX RANGE SCAN | UX2_TEMP_AU_COMPANY | 3187 | 54179 | 3 |
    | 3 | TABLE ACCESS FULL | AU_COMPANY | 24009 | 492K| 2983 |
    Any other ideas? They should be the same.
    Brenda

Maybe you are looking for