Explain Plan Difference
Hi All,
I have two users Here user1 and user2 which will access tables from user3
If I run a query from USER1 then I am getting a very good execution plan
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost | Pstart| Pstop |
| 0 | SELECT STATEMENT | | 1 | 138 | 14 | | |
| 1 | NESTED LOOPS | | 1 | 138 | 14 | | |
| 2 | NESTED LOOPS | | 2 | 144 | 12 | | |
| 3 | SORT UNIQUE | | 1 | 25 | 4 | | |
| 4 | PARTITION LIST SINGLE | | 1 | 25 | 4 | KEY | KEY |
| 5 | TABLE ACCESS BY LOCAL INDEX ROWID| TBL_SUBR_INDV | 1 | 25 | 4 | KEY | KEY |
| 6 | INDEX RANGE SCAN | DCS_INDIVIDUAL_IDENTIFIER_IX | 1 | | 3 | KEY | KEY |
| 7 | TABLE ACCESS BY GLOBAL INDEX ROWID | TBL_SUBR_INDV | 1 | 47 | 4 | ROWID | ROWID |
| 8 | INDEX RANGE SCAN | PK_SUBR_INDV | 2 | | 2 | | |
| 9 | PARTITION LIST SINGLE | | 1 | 66 | 1 | KEY | KEY |
| 10 | TABLE ACCESS BY LOCAL INDEX ROWID | TBL_GSD | 1 | 66 | 1 | KEY | KEY |
| 11 | INDEX UNIQUE SCAN | PK_GSD_PK_LCL | 1 | | | KEY | KEY |
Note
- 'PLAN_TABLE' is old version
- cpu costing is off (consider enabling it)If I run the query from USER2 its killing..
PLAN_TABLE_OUTPUT
Plan hash value: 3576012501
| Id | Operation | Name | Rows | Bytes | Cost | Pstart| Pstop |
| 0 | SELECT STATEMENT | | 1 | 213 | 4004K| | |
| 1 | NESTED LOOPS | | 1 | 213 | 4004K| | |
| 2 | NESTED LOOPS | | 1 | 119 | 3994K| | |
| 3 | SORT UNIQUE | | 1 | 25 | 4 | | |
| 4 | PARTITION LIST SINGLE | | 1 | 25 | 4 | KEY | KEY |
|* 5 | TABLE ACCESS BY LOCAL INDEX ROWID| TBL_SUBR_INDV | 1 | 25 | 4 | KEY | KEY |
|* 6 | INDEX RANGE SCAN | DCS_INDIVIDUAL_IDENTIFIER_IX | 1 | | 3 | KEY | KEY |
|* 7 | VIEW | TBL_SUBR_INDV | 1 | 94 | 3994K| | |
|* 8 | TABLE ACCESS BY GLOBAL INDEX ROWID| TBL_SUBR_INDV | 2083K| 93M| 3994K| ROWID | ROWID |
|* 9 | INDEX RANGE SCAN | PK_SUBR_INDV | 4568K| | 22399 | | |
| 10 | PARTITION LIST SINGLE | | 1 | 94 | 9719 | KEY | KEY |
|* 11 | VIEW | TBL_GSD | 1 | 94 | 9719 | | |
|* 12 | TABLE ACCESS BY LOCAL INDEX ROWID | TBL_GSD | 19398 | 1250K| 9719 | KEY | KEY |
|* 13 | INDEX RANGE SCAN | PK_GSD_PK_LCL | 38795 | | 98 | KEY | KEY |
Predicate Information (identified by operation id):
5 - filter("PARENT_ID"=TO_NUMBER(SYS_CONTEXT('CNT_PARENT_ID','PARENT_ID')))
6 - access("DCS_INDIVIDUAL_IDENTIFIER"='2236793')
7 - filter("A"."SUBR_ID"="SUBR_ID")
8 - filter("RELSHP_CDE"=1 AND NVL("MAINT_CODE",0)=0)
9 - access("PARENT_ID"=TO_NUMBER(SYS_CONTEXT('CNT_PARENT_ID','PARENT_ID')))
11 - filter("B"."GSD_PK"="PKG_ALTERNATE_ID_UTILS"."FNC_GET_SUBR_CVRG_GSD"("A"."SUBR_ID"))
12 - filter(NVL("MAINT_CODE",0)=0)
13 - access("PARENT_ID"=TO_NUMBER(SYS_CONTEXT('CNT_PARENT_ID','PARENT_ID')))
Note
- cpu costing is off (consider enabling it)Is there any particular reason this could happen?
Any Ideas?
G.
- we are not allowed to get a 4-digit version number -- I apologize 10.2.04
- we are not allowed to see the SQL statements -- Nothing to with that
As my post clearly asks a simple question... Can explain plans differ when accessing from two different users?
If so, what could be the reason.
- after statement 1 the PLAN_TABLE was recreated, resulting in incompatible output -- No.
But I still apologize because I didnot mention that there is a VPD setup. and USER1 has DBA privelige and USER2 doesnot. thats the reason it is using two different execution plans as DBA can exempt VPD for execution plan.
Now my question is,
I cannot grant DBA to USER2, How can I get the same execution plan as USER1?
I have tried the execmpt access policy grant, But didnot work.. It increased the cost.
Any Ideas?
G.
Similar Messages
-
Same query, same dataset, same ddl setup, but wildly different explain plan
Hello o fountains of oracle knowledge!
We have a problem that caused us a full stop when rolling out a new version of our system to a customer and a whole Sunday to boot.
The scenario is as follows:
1. An previous version database schema
2. The current version database schema
3. A migration script to migrate the old schema to the new
So we perform the following migration:
1. Export the previous version database schema
2. Import into a new schema called schema_old
3. Create a new schema called schema_new
4. Run migration script which creates objects, copies data, creates indexes etc etc in schema_new
The migration runs fine in all environments (development, test and production)
In our development and test environments performance is stellar, on the customer production server the performance is terrible.
This using the exact same export file (from the production environment) and performing the exact same steps with the exact same migration script.
Database version is 10.2.0.1.0 EE on all databases. OS is Microsoft Windows Server 2003 EE SP2 on all servers.
The system is not in any sense under a heavy load (we have tested with no other load than ourselves).
Looking at the explain plan for a query that is run frequently and does not use bind variables we see wildly different explain plans.
The explain plan cost on our development and test servers is estimated to *7* for this query and there are no full table scans.
On the production server the cost is *8433* and there are two full table scans of which one is on the largest table.
We have tried to run analyse on all objects with very little effect. The plan changed very slightly, but still includes the two full table scans on the problem server and the cost is still the same.
All tables and indexes are identical (including storage options), created from the same migration script.
I am currently at loss for where to look? What can be causing this? I assume this could be caused by some parameter that is set on the server, but I don't know what to look for.
I would be very grateful for any pointers.
Thanks,
HåkonThank you for your answer.
We collected statistics only after we determined that the production server where not behaving according to expectations.
In this case we used TOAD and the tool within to collect statistics for all objects. We used 'Analyze' and 'Compute Statistics' options.
I am not an expert, so sorry if this is too naive an approach.
Here is the query:SELECT count(0)
FROM score_result sr, web_scorecard sc, product p
WHERE sr.score_final_decision like 'VENT%'
AND sc.CREDIT_APPLICATION_ID = sr.CREDIT_APPLICATION_ID
AND sc.application_complete='Y'
AND p.product = sc.web_product
AND p.inactive_product = '2' ;I use this as an example, but the problem exists for virtually all queries.
The output from the 'good' server:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | SELECT STATEMENT | | 1 | 39 | 7 (0)|
| 1 | SORT AGGREGATE | | 1 | 39 | |
| 2 | NESTED LOOPS | | 1 | 39 | 7 (0)|
| 3 | NESTED LOOPS | | 1 | 30 | 6 (0)|
| 4 | TABLE ACCESS BY INDEX ROWID| SCORE_RESULT | 1 | 17 | 4 (0)|
| 5 | INDEX RANGE SCAN | SR_FINAL_DECISION_IDX | 1 | | 3 (0)|
| 6 | TABLE ACCESS BY INDEX ROWID| WEB_SCORECARD | 1 | 13 | 2 (0)|
| 7 | INDEX UNIQUE SCAN | WEB_SCORECARD_PK | 1 | | 1 (0)|
| 8 | TABLE ACCESS BY INDEX ROWID | PRODUCT | 1 | 9 | 1 (0)|
| 9 | INDEX UNIQUE SCAN | PK_PRODUCT | 1 | | 0 (0)|
---------------------------------------------------------------------------------------------The output from the 'bad' server:
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | SELECT STATEMENT | | 1 | 32 | 8344 (3)|
| 1 | SORT AGGREGATE | | 1 | 32 | |
| 2 | HASH JOIN | | 10887 | 340K| 8344 (3)|
| 3 | TABLE ACCESS FULL | PRODUCT | 6 | 42 | 3 (0)|
| 4 | HASH JOIN | | 34381 | 839K| 8340 (3)|
| 5 | VIEW | index$_join$_001 | 34381 | 503K| 2193 (3)|
| 6 | HASH JOIN | | | | |
| 7 | INDEX RANGE SCAN | SR_FINAL_DECISION_IDX | 34381 | 503K| 280 (3)|
| 8 | INDEX FAST FULL SCAN| SCORE_RESULT_PK | 34381 | 503K| 1371 (2)|
| 9 | TABLE ACCESS FULL | WEB_SCORECARD | 489K| 4782K| 6137 (4)|
----------------------------------------------------------------------------------------I hope the formatting makes this readable.
Stats (from SQL Developer), good table:NUM_ROWS 489716
BLOCKS 27198
AVG_ROW_LEN 312
SAMPLE_SIZE 489716
LAST_ANALYZED 15.12.2009
LAST_ANALYZED_SINCE 15.12.2009Stats (from SQL Developer), bad table:
NUM_ROWS 489716
BLOCKS 27199
AVG_ROW_LEN 395
SAMPLE_SIZE 489716
LAST_ANALYZED 17.12.2009
LAST_ANALYZED_SINCE 17.12.2009I'm unsure what would cause the difference in average row length.
I could obviously try to tune our sql-statements to work on the server not behaving better, but I would rather understand why they are different and make sure that we can expect similar behaviour between environments.
Thank you again for trying to help me.
Håkon
Edited by: ergates on 17.des.2009 05:57
Edited by: ergates on 17.des.2009 06:02 -
Oracle not using its own explain plan
When I run a simple select query on an indexed column on a large (30 million records) table oracle creates a plan using the indexed column and at a cost of 4. However, what it actually does is do a table scan (I can see this in the 'Long Operations' tab in OEM).
The funny thing is that I have the same query in a ADO application and when the query is run from there, the same plan is created but no table scan is done - and the query returns in less than a second. However, with the table scan it is over a minute.
When run through SQL plus Oracle creates a plan including the table scan at a cost of 19030.
In another (dot net) application I used the: "Alter session set optimizer_index_caching=100" and "Alter session set optimizer_index_cost_adj=10" to try to force the optimizer to use the index. It creates the expected plan, but still does the table scan.
The query is in the form of:
"Select * from tab where indexedcol = something"
Im using Oracle 9i 9.2.0.1.0
Any ideas as I'm completely at a loss?Hello
It sounds to me like this has something to do with bind variable peeking which was introduced in 9i. If the predicate is
indexedcolumn = :bind_variablethe first time the query is parsed by oracle, it will "peek" at the value in the bind variable and see what it is and will generate an execution plan based on this. That same plan will be used for matching SQL.
If you use a litteral, it will generate the plan based on that, and will generate a separate plan for each litteral you use (depending on the value of the cursor_sharing initialisation parameter).
This can cause there to be a difference between the execution plan seen when issuing EXPLAIN PLAN FOR, and the actual exectuion plan used when the query is run.
Have a look at the following example:
tylerd@DEV2> CREATE TABLE dt_test_bvpeek(id number, col1 number)
2 /
Table created.
Elapsed: 00:00:00.14
tylerd@DEV2> INSERT
2 INTO
3 dt_test_bvpeek
4 SELECT
5 rownum,
6 CASE
7 WHEN MOD(rownum, 5) IN (0,1,2,3) THEN
8 1
9 ELSE
10 MOD(rownum, 5)
11 END
12 END
13 FROM
14 dual
15 CONNECT BY
16 LEVEL <= 100000
17 /
100000 rows created.
Elapsed: 00:00:00.81
tylerd@DEV2> select count(*), col1 from dt_test_bvpeek group by col1
2 /
COUNT(*) COL1
80000 1
20000 4
2 rows selected.
Elapsed: 00:00:00.09
tylerd@DEV2> CREATE INDEX dt_test_bvpeek_i1 ON dt_test_bvpeek(col1)
2 /
Index created.
Elapsed: 00:00:00.40
tylerd@DEV2> EXEC dbms_stats.gather_table_stats( ownname=>USER,-
tabname=>'DT_TEST_BVPEEK',-
method_opt=>'FOR ALL INDEXED COLUMNS SIZE 254',-
cascade=>TRUE -
);PL/SQL procedure successfully completed.
Elapsed: 00:00:00.73
tylerd@DEV2> EXPLAIN PLAN FOR
2 SELECT
3 *
4 FROM
5 dt_test_bvpeek
6 WHERE
7 col1 = 1
8 /
Explained.
Elapsed: 00:00:00.01
tylerd@DEV2> SELECT * FROM TABLE(DBMS_XPLAN.display)
2 /
PLAN_TABLE_OUTPUT
Plan hash value: 2611346395
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 78728 | 538K| 82 (52)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| DT_TEST_BVPEEK | 78728 | 538K| 82 (52)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("COL1"=1)
13 rows selected.
Elapsed: 00:00:00.06The execution plan for col1=1 was chosen because oracle was able to see that based on the statistics, col1=1 would result in most of the rows from the table being returned.
tylerd@DEV2> EXPLAIN PLAN FOR
2 SELECT
3 *
4 FROM
5 dt_test_bvpeek
6 WHERE
7 col1 = 4
8 /
Explained.
Elapsed: 00:00:00.00
tylerd@DEV2> SELECT * FROM TABLE(DBMS_XPLAN.display)
2 /
PLAN_TABLE_OUTPUT
Plan hash value: 3223879139
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 21027 | 143K| 74 (21)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| DT_TEST_BVPEEK | 21027 | 143K| 74 (21)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | DT_TEST_BVPEEK_I1 | 21077 | | 29 (28)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("COL1"=4)
14 rows selected.
Elapsed: 00:00:00.04This time, the optimiser was able to see that col1=4 would result in far fewer rows so it chose to use an index. Look what happens however when we use a bind variable with EXPLAIN PLAN FOR - especially the number of rows the optimiser estimates to be returned from the table
tylerd@DEV2> var an_col1 NUMBER
tylerd@DEV2> exec :an_col1:=1;
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
tylerd@DEV2>
tylerd@DEV2> EXPLAIN PLAN FOR
2 SELECT
3 *
4 FROM
5 dt_test_bvpeek
6 WHERE
7 col1 = :an_col1
8 /
Explained.
Elapsed: 00:00:00.01
tylerd@DEV2> SELECT * FROM TABLE(DBMS_XPLAN.display)
2 /
PLAN_TABLE_OUTPUT
Plan hash value: 2611346395
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 49882 | 340K| 100 (60)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| DT_TEST_BVPEEK | 49882 | 340K| 100 (60)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("COL1"=TO_NUMBER(:AN_COL1))
13 rows selected.
Elapsed: 00:00:00.04
tylerd@DEV2>
tylerd@DEV2> exec :an_col1:=4;
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
tylerd@DEV2>
tylerd@DEV2> EXPLAIN PLAN FOR
2 SELECT
3 *
4 FROM
5 dt_test_bvpeek
6 WHERE
7 col1 = :an_col1
8 /
Explained.
Elapsed: 00:00:00.01
tylerd@DEV2> SELECT * FROM TABLE(DBMS_XPLAN.display)
2 /
PLAN_TABLE_OUTPUT
Plan hash value: 2611346395
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 49882 | 340K| 100 (60)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| DT_TEST_BVPEEK | 49882 | 340K| 100 (60)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("COL1"=TO_NUMBER(:AN_COL1))
13 rows selected.
Elapsed: 00:00:00.07For both values of the bind variable, the optimiser has no idea what the value will be so it has to make a calculation based on a formula which results in it estimating that the query will return roughly half of the rows in the table, and so it chooses a full scan.
Now when we actually run the query, the optimiser can take advantage of bind variable peeking and have a look at the value the first time round and base the execution plan on that:
tylerd@DEV2> exec :an_col1:=1;
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
tylerd@DEV2> SELECT
2 *
3 FROM
4 dt_test_bvpeek
5 WHERE
6 col1 = :an_col1
7 /
80000 rows selected.
Elapsed: 00:00:10.98
tylerd@DEV2> SELECT prev_sql_id FROM v$session WHERE audsid=SYS_CONTEXT('USERENV','SESSIONID')
2 /
PREV_SQL_ID
9t52uyyq67211
1 row selected.
Elapsed: 00:00:00.00
tylerd@DEV2> SELECT
2 operation,
3 options,
4 object_name
5 FROM
6 v$sql_plan
7 WHERE
8 sql_id = '9t52uyyq67211'
9 /
OPERATION OPTIONS OBJECT_NAME
SELECT STATEMENT
TABLE ACCESS FULL DT_TEST_BVPEEK
2 rows selected.
Elapsed: 00:00:00.03It saw that the bind variable value was 1 and that this would return most of the rows in the table so it chose a full scan.
tylerd@DEV2> exec :an_col1:=4
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
tylerd@DEV2> SELECT
2 *
3 FROM
4 dt_test_bvpeek
5 WHERE
6 col1 = :an_col1
7 /
20000 rows selected.
Elapsed: 00:00:03.50
tylerd@DEV2> SELECT prev_sql_id FROM v$session WHERE audsid=SYS_CONTEXT('USERENV','SESSIONID')
2 /
PREV_SQL_ID
9t52uyyq67211
1 row selected.
Elapsed: 00:00:00.00
tylerd@DEV2> SELECT
2 operation,
3 options,
4 object_name
5 FROM
6 v$sql_plan
7 WHERE
8 sql_id = '9t52uyyq67211'
9 /
OPERATION OPTIONS OBJECT_NAME
SELECT STATEMENT
TABLE ACCESS FULL DT_TEST_BVPEEK
2 rows selected.
Elapsed: 00:00:00.01Even though the value of the bind variable changed, the optimiser saw that it already had a cached version of the sql statement along with an execution plan, so it used that rather than regenerating the plan. We can check the reverse of this by causing the statement to be invalidated and re-parsed - there's lots of ways, but I'm just going to rename the table:
Elapsed: 00:00:00.03
tylerd@DEV2> alter table dt_test_bvpeek rename to dt_test_bvpeek1
2 /
Table altered.
Elapsed: 00:00:00.01
tylerd@DEV2>
20000 rows selected.
Elapsed: 00:00:04.81
tylerd@DEV2> SELECT prev_sql_id FROM v$session WHERE audsid=SYS_CONTEXT('USERENV','SESSIONID')
2 /
PREV_SQL_ID
6ztnn4fyt6y5h
1 row selected.
Elapsed: 00:00:00.00
tylerd@DEV2> SELECT
2 operation,
3 options,
4 object_name
5 FROM
6 v$sql_plan
7 WHERE
8 sql_id = '6ztnn4fyt6y5h'
9 /
OPERATION OPTIONS OBJECT_NAME
SELECT STATEMENT
TABLE ACCESS BY INDEX ROWID DT_TEST_BVPEEK1
INDEX RANGE SCAN DT_TEST_BVPEEK_I1
3 rows selected.
80000 rows selected.
Elapsed: 00:00:10.61
tylerd@DEV2> SELECT prev_sql_id FROM v$session WHERE audsid=SYS_CONTEXT('USERENV','SESSIONID')
2 /
PREV_SQL_ID
6ztnn4fyt6y5h
1 row selected.
Elapsed: 00:00:00.01
tylerd@DEV2> SELECT
2 operation,
3 options,
4 object_name
5 FROM
6 v$sql_plan
7 WHERE
8 sql_id = '6ztnn4fyt6y5h'
9 /
OPERATION OPTIONS OBJECT_NAME
SELECT STATEMENT
TABLE ACCESS BY INDEX ROWID DT_TEST_BVPEEK1
INDEX RANGE SCAN DT_TEST_BVPEEK_I1
3 rows selected.This time round, the optimiser peeked at the bind variable the first time the statement was exectued and found it to be 4, so it based the execution plan on that and chose an index range scan. When the statement was executed again, it used the plan it had already executed.
HTH
David -
Explain plan different for same query
Hi all,
I have a query, which basically selects some columns from a remote database view. The query is as follows:
select * from tab1@remotedb, tab2@remotedb
where tab1.cash_id = tab2.id
and tab1.date = '01-JAN-2003'
and tab2.country_code = 'GB';
Now, i am working on two environments, one is production and other is development. Production environment has following specification:
1. Remotedb = Oracle9i, Linux OS
2. Database on which query is running = Oracle10g, Linux OS
Development environment has following specification:
1. Remotedb = Oracle10g, Windows OS
2. Database on which query is running = Oracle10g, Linux OS
Both databases in development and production environments are on different machines.
when i execute the above query on production, i see full table scans on both tables in execution plan(TOAD), but when i execute the query in development, i see that both remote database tables are using index.
Why am i getting different execution plans on both databases? is there is any difference of user rights/priviliges or there is a difference of statistics on both databases. I have checked the statistics for both tables on Production and Development databases, they are updated.
This issue is creating a performance disaster in our Production system. Any kind of help or knowledge sharing is appreciated.
Thank you and Best Regards.We ran into a similar situation yesterday morning, though our implementation was easier than yours. Different plans in development and production though both systems were 10gR2 at the time. Production was doing a Merge Join Cartesian (!) instead of nested loop joins. Our DBA figured out that the production stats had been locked for some tables preventing stat refresh; she unlocked them and re-analyzed so which fixed our problem.
Of some interest was discovering that I got different execution plans from the same UPDATE via EXPLAIN PLAN and SQL*PLUS AUTOTRACE in development. Issue appears to have been bind peeking. Converting bind variables to constants yielded the AUTOTRACE plan, as did turning bind peeking off while using the bind variables. CURSOR_SHARING was set to EXACT too.
Message was edited by:
riedelme -
Execution Time & Explain Plan Variations
I have a scenario here. I have 2 schemas; schema1 & schema2. I executed a lengthy SELECT statement of 5 TABLE JOIN in these 2 schemas. I am getting totally different execution time (one runs at 0.3 seconds & the other at 4 seconds) and a different Explain Plan. I assume that, since its the same SELECT statement in these schema, I should get the same Explain Plan. What could be the reason for these dissimilarities? Oracle Version: 9.2.0.8.0. I am ready to share the Explain Plan of these 2 schemas. But they are of length around 300 lines.
Thank you.There are many factors come in to play here.
1.) Size of all tables involved are same
2.) structures are also same
3.) Also indexes are same
4.) Also stats are up to date on both
5.) Constraints and other factors are also same.
regards
PravinAnd a few more.
6) session environments are the same
7) bind variable values are the same - or were at first execution
I'd change 4 to read Optimizer statistics are the same. (not up to date which is a bit vague).
In short if you are using the CBO and feed in the exact same inputs you will get the exact same plan, however typically you won't get the exact same inputs and so may get a different plan. If your query has a time element and the two queries are hard parsed at different times it may actually be impossible to get the same input - for example the percentage of a table that is returned by a predicate like
timestamp_col > sysdate - 1 will be estimated differently depending on the time of parsing for the same data.
That all said looking at the plans might reveal some obvious differences, though perhaps it might be better to point at a URL that holds the plans given the length you say they are.
Niall Litchfield
http://www.orawin.info/
null -
Diff in explain plan of 9i and 10g
I am beginner and just started my dba career. Please can you help me by giving me the differences between a explain plan executed in oracle 9i and 10g. Why is there variations in the cost,cardinality and bytes. Is it that 9is explain plan is executed in a different way when compared to 10g's. Please help me out regarding the same.
Are your generating it against same sets of rows or using different tables ? we would love to see more information and could you please your explain plan on the board ?
hare krishna
Alok -
I have EXPLAIN PLAN results for some SELECT queries. What is the difference between INDEX UNIQUE SCAN and INDEX RANGE SCAN?
btw it depend not only of your compare operation
but also on index type. See difference for equality between simple index and unique index:
SQL> desc a
Name Null? Type
A NUMBER
SQL> create index aidx on a (a);
Index created.
SQL> set autot traceonly explain
SQL> select * from a where a = 1;
Execution Plan
Plan hash value: 3649445643
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| AIDX | 1 | 13 | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("A"=1)
SQL> drop index aidx;
Index dropped.
SQL> create unique index aidx on a (a);
Index created.
SQL> select * from a where a = 1;
Execution Plan
Plan hash value: 2717653437
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 13 | 0 (0)| 00:00:01 |
|* 1 | INDEX UNIQUE SCAN| AIDX | 1 | 13 | 0 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("A"=1)
SQL> Of course even with unique index >, <, between will have range scan:
SQL> select * from a where a>1;
Execution Plan
Plan hash value: 3649445643
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 13 | 0 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| AIDX | 1 | 13 | 0 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("A">1)
SQL> In general index range scan might expect back more than 1 row, while index unique scan usually expect 1 row, however of course in both cases you might get zero rows back.
See my blog entry Where bad performance starts at http://gplivna.blogspot.com/2007/03/where-bad-performance-starts-my.html
it has many links aboput b-tree index internals, I'm quite sure some of them explained these operations more as well.
Gints Plivna
http://www.gplivna.eu -
Explain Plan vs. V$SQL_PLAN
Hello everyone,
I'm trying to understand the difference between those two, I'm relying on the following Tom Kyte article :
http://tkyte.blogspot.com/2007/04/when-explanation-doesn-sound-quite.html
In my following example I didn't use TKPROF as he did but AUTOTRACE / V$SQL_PLAN instead (since EXPLAIN PLAN shows a theoretical plan that can be used if this statement were to be executed and V$SQL_PLAN contains the actual plan used)
That's my code :
>
HR> ALTER SYSTEM FLUSH shared_pool ;
HR>
HR> create table test
2 as
3 select a.*, 1 id
4 from all_objects a
5 where rownum = 1;
Table created.
HR>
HR> create index t_idx on test(id);
Index created.
HR>
HR> -- AUTOTRACE vs V$SQL round 1 ...
HR> ---------------------------------
HR>
HR> SET AUTOTRACE ON EXPLAIN
HR>
HR> select id, object_name from test where id = 1;
ID OBJECT_NAME
1 ICOL$
Execution Plan
Plan hash value: 2783519773
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 30 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("ID"=1)
Note
- dynamic sampling used for this statement (level=2)
HR>
HR> SET AUTOTRACE OFF
HR>
HR>
HR> select operation, options, object_name, cost
2 from v$sql_plan
3 where hash_value= ( SELECT hash_value
4 FROM v$sqlarea
5 WHERE sql_text LIKE 'select id, object_name from test where id = 1'
6 AND sql_text NOT LIKE '%v_sql%');
OPERATION OPTIONS OBJECT_NAME COST
SELECT STATEMENT 2
TABLE ACCESS BY INDEX ROWID TEST 2
INDEX RANGE SCAN T_IDX 1
>
Ok so in round 1, the optimizer decided to get the 1 row back using Index Range Scan both in "theory" and in "reality", it make sense.
Now its time for round 2 ... :)
>
HR> insert into test select a.*, 1 from all_objects a where rownum < 1001 ;
1000 rows created.
HR>
HR> commit ;
Commit complete.
HR>
HR>
HR> -- AUTOTRACE vs V$SQL round 2 ...
HR> ---------------------------------
HR>
HR> SET AUTOTRACE ON EXPLAIN
HR>
HR> select id, object_name from test where id = 1;
ID OBJECT_NAME
1 ICOL$
1 I_VIEWTRCOL1
1001 rows selected.
Execution Plan
Plan hash value: 2783519773
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1001 | 30030 | 6 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1001 | 30030 | 6 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 1001 | | 5 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("ID"=1)
Note
- dynamic sampling used for this statement (level=2)
HR>
HR> select operation, options, object_name, cost
2 from v$sql_plan
3 where hash_value= ( SELECT hash_value
4 FROM v$sqlarea
5 WHERE sql_text LIKE 'select id, object_name from test where id = 1'
6 AND sql_text NOT LIKE '%v_sql%');
OPERATION OPTIONS OBJECT_NAME COST
SELECT STATEMENT 2
TABLE ACCESS BY INDEX ROWID TEST 2
INDEX RANGE SCAN T_IDX 1
HR>
>
since explain plan is using always Hard Parse (and it used dynamic sampling) I would expect to see FTS in "theory"
can anyone explain me why in round 2 they both presented Index Range Scan.
Thanks ! :)Explain plan can lie, autotrace - which just does an explain plan - can lie.
See:
http://oracle-randolf.blogspot.com/2012/01/autotrace-polluting-shared-pool.html
http://kerryosborne.oracle-guy.com/2010/02/autotrace-lies/
http://hoopercharles.wordpress.com/2010/01/11/explain-plan-lies-autotrace-lies-tkprof-lies-what-is-the-plan/
V$SQL_PLAN is the truth.
You didn't mention version but DBMS_XPLAN is the most convenient way to get your plan.
If the plan is cached, inserting 1000 rows is not going to change the plan.
SQL> create table test
2 as
3 select a.*, 1 id
4 from all_objects a
5 where rownum = 1;
Table created.
SQL>
SQL> create index t_idx on test(id);
Index created.
SQL>
SQL> select id, object_name from test where id = 1;
ID OBJECT_NAME
1 ORA$BASE
SQL>
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID 3qan6s0j3uab5, child number 0
select id, object_name from test where id = 1
Plan hash value: 2783519773
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("ID"=1)
Note
- dynamic sampling used for this statement (level=4)
23 rows selected.
SQL> insert into test select a.*, 1 from all_objects a where rownum < 1001 ;
1000 rows created.
SQL> commit;
Commit complete.
SQL> select id, object_name from test where id = 1;
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
SQL_ID 3qan6s0j3uab5, child number 0
select id, object_name from test where id = 1
Plan hash value: 2783519773
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
2 - access("ID"=1)
Note
- dynamic sampling used for this statement (level=4)
23 rows selected.
SQL> -
The below same query runs fast at PL/SQL , while the same query run from front end (EBS R 12.0.4) using concurrent request runs verl slow , both has diffrent plan , please share some thought.
Below query when i run from backend (PL/SQL Developer) it returns row within a second
SELECT /*+ gather_plan_statistics product_item_2.txt */ OH.ORG_ID,BUNIT.BU_ID,OL.INVENTORY_ITEM_ID,CUST.account_number,CUST.ACCOUNT_NAME,CUST.CUSTOMER_CLASS_CODE,
NVL(SUM(OL.FULFILLED_QUANTITY),0) as sale_qty
FROM
OE_ORDER_HEADERS_ALL OH,OE_ORDER_LINES_ALL OL,
HZ_CUST_ACCOUNTS CUST,mtl_categories_vl CAT,
mtl_item_categories IC,(select FLEX_VALUE BU_ID,DESCRIPTION B_NAME from fnd_flex_values_vl t
where t.FLEX_VALUE_SET_ID ='1012990') BUNIT
WHERE OH.HEADER_ID = OL.HEADER_ID
AND CUST.CUST_ACCOUNT_ID =
(SELECT DISTINCT ACCT.CUST_ACCOUNT_ID
FROM HZ_CUST_ACCOUNTS ACCT,HZ_CUST_ACCT_SITES_ALL ACCT_SITE,
HZ_LOCATIONS LOC,HZ_PARTY_SITES PARTY_SITE,
HZ_CUST_SITE_USES_ALL SUSE,HZ_PARTIES P
WHERE ACCT.PARTY_ID = PARTY_SITE.PARTY_ID
AND ACCT.CUST_ACCOUNT_ID = ACCT_SITE.CUST_ACCOUNT_ID
AND SUSE.CUST_ACCT_SITE_ID = ACCT_SITE.CUST_ACCT_SITE_ID
AND ACCT_SITE.PARTY_SITE_ID = PARTY_SITE.PARTY_SITE_ID
AND LOC.LOCATION_ID = PARTY_SITE.LOCATION_ID
AND SUSE.SITE_USE_ID = OL.SHIP_TO_ORG_ID
AND P.PARTY_ID = ACCT.PARTY_ID
AND P.PARTY_ID = PARTY_SITE.PARTY_ID
AND SUSE.SITE_USE_CODE = 'SHIP_TO'
AND ACCT_SITE.ORG_ID = &P_ORG_ID
AND OH.ORG_ID = &P_ORG_ID
AND OL.ACTUAL_SHIPMENT_DATE BETWEEN &P_FROM_DATE AND &P_TO_DATE
AND OL.UNIT_SELLING_PRICE != 0
AND OL.LINE_CATEGORY_CODE = 'ORDER'
AND OL.ORDERED_ITEM = NVL(&ITEM_HIGH, OL.ORDERED_ITEM)
AND BUNIT.BU_ID = nvl(&p_business_unit,bunit.bu_id)
AND CAT.CATEGORY_ID = IC.CATEGORY_ID
AND CAT.STRUCTURE_ID = 50289
AND IC.INVENTORY_ITEM_ID = OL.INVENTORY_ITEM_ID
AND IC.ORGANIZATION_ID = OH.SHIP_FROM_ORG_ID
and cat.SEGMENT3 = BUNIT.BU_ID
GROUP BY
OH.ORG_ID,BUNIT.BU_ID,OL.INVENTORY_ITEM_ID,CUST.account_number,CUST.ACCOUNT_NAME,CUST.CUSTOMER_CLASS_CODE
ORDER BY 1Plan for above query is as follows
SQL> set pagesize 1000
SQL> /
PLAN_TABLE_OUTPUT
SQL_ID 5g71mvqaat8x3, child number 0
Plan hash value: 610424373
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
| 1 | HASH GROUP BY | | 1 | 1 | 2 |00:00:00.64 | 144K| | | |
| 2 | NESTED LOOPS | | 1 | 1 | 71 |00:00:00.30 | 144K| | | |
| 3 | NESTED LOOPS | | 1 | 1 | 1704 |00:00:00.26 | 138K| | | |
|* 4 | HASH JOIN | | 1 | 1 | 3312 |00:00:00.05 | 132K| 887K| 887K| 1236K (0)|
| 5 | TABLE ACCESS BY INDEX ROWID | MTL_ITEM_CATEGORIES | 1 | 506 | 1075 |00:00:00.02 | 361 | | | |
| 6 | NESTED LOOPS | | 1 | 1 | 1077 |00:00:00.04 | 24 | | | |
| 7 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 19 | | | |
| 8 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 18 | | | |
| 9 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 15 | | | |
|* 10 | TABLE ACCESS BY INDEX ROWID | FND_FLEX_VALUES | 1 | 1 | 1 |00:00:00.01 | 13 | | | |
|* 11 | INDEX RANGE SCAN | IDX$$_65860003 | 1 | 22 | 52 |00:00:00.01 | 2 | | | |
|* 12 | INDEX UNIQUE SCAN | FND_FLEX_VALUES_TL_U1 | 1 | 1 | 1 |00:00:00.01 | 2 | | | |
|* 13 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORIES_B | 1 | 1 | 1 |00:00:00.01 | 3 | | | |
|* 14 | INDEX RANGE SCAN | IDX$$_79530001 | 1 | 1 | 2 |00:00:00.01 | 1 | | | |
|* 15 | INDEX UNIQUE SCAN | MTL_CATEGORIES_TL_U1 | 1 | 1 | 1 |00:00:00.01 | 1 | | | |
|* 16 | INDEX RANGE SCAN | IDX$$_78250002 | 1 | 1528 | 1075 |00:00:00.01 | 5 | | | |
|* 17 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_LINES_ALL | 1 | 51 | 138 |00:00:00.01 | 132K| | | |
|* 18 | INDEX SKIP SCAN | OE_ORDER_LINES_N26 | 1 | 14977 | 113K|00:00:00.57 | 1208 | | | |
| 19 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_ACCOUNTS | 3312 | 1 | 1704 |00:00:00.09 | 5188 | | | |
|* 20 | INDEX UNIQUE SCAN | HZ_CUST_ACCOUNTS_U1 | 3312 | 1 | 1704 |00:00:00.04 | 3484 | | | |
| 21 | NESTED LOOPS | | 8 | 1 | 2 |00:00:00.01 | 76 | | | |
| 22 | NESTED LOOPS | | 8 | 1 | 2 |00:00:00.01 | 72 | | | |
| 23 | NESTED LOOPS | | 8 | 1 | 2 |00:00:00.01 | 66 | | | |
| 24 | NESTED LOOPS | | 8 | 1 | 2 |00:00:00.01 | 62 | | | |
| 25 | NESTED LOOPS | | 8 | 1 | 2 |00:00:00.01 | 56 | | | |
|* 26 | TABLE ACCESS BY INDEX ROWID| HZ_CUST_SITE_USES_ALL | 8 | 1 | 8 |00:00:00.01 | 32 | | | |
|* 27 | INDEX UNIQUE SCAN | HZ_CUST_SITE_USES_U1 | 8 | 1 | 8 |00:00:00.01 | 24 | | | |
|* 28 | TABLE ACCESS BY INDEX ROWID| HZ_CUST_ACCT_SITES_ALL | 8 | 25087 | 2 |00:00:00.01 | 24 | | | |
|* 29 | INDEX UNIQUE SCAN | HZ_CUST_ACCT_SITES_U1 | 8 | 1 | 8 |00:00:00.01 | 16 | | | |
| 30 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_ACCOUNTS | 2 | 176K| 2 |00:00:00.01 | 6 | | | |
|* 31 | INDEX UNIQUE SCAN | HZ_CUST_ACCOUNTS_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
|* 32 | INDEX UNIQUE SCAN | HZ_PARTIES_U1 | 2 | 176K| 2 |00:00:00.01 | 4 | | | |
|* 33 | TABLE ACCESS BY INDEX ROWID | HZ_PARTY_SITES | 2 | 188K| 2 |00:00:00.01 | 6 | | | |
|* 34 | INDEX UNIQUE SCAN | HZ_PARTY_SITES_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
|* 35 | INDEX UNIQUE SCAN | HZ_LOCATIONS_U1 | 2 | 174K| 2 |00:00:00.01 | 4 | | | |
|* 36 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_HEADERS_ALL | 1704 | 1 | 71 |00:00:00.05 | 6816 | | | |
|* 37 | INDEX UNIQUE SCAN | OE_ORDER_HEADERS_U1 | 1704 | 1 | 1704 |00:00:00.03 | 5112 | | | |
Predicate Information (identified by operation id):
4 - access("IC"."INVENTORY_ITEM_ID"="OL"."INVENTORY_ITEM_ID")
10 - filter("B"."FLEX_VALUE"=NVL('02',"B"."FLEX_VALUE"))
11 - access("B"."FLEX_VALUE_SET_ID"=1012990)
12 - access("B"."FLEX_VALUE_ID"="T"."FLEX_VALUE_ID" AND "T"."LANGUAGE"=USERENV('LANG'))
13 - filter("B"."STRUCTURE_ID"=50289)
14 - access("B"."SEGMENT3"="B"."FLEX_VALUE")
filter("B"."SEGMENT3" IS NOT NULL)
15 - access("B"."CATEGORY_ID"="T"."CATEGORY_ID" AND "T"."LANGUAGE"=USERENV('LANG'))
16 - access("B"."CATEGORY_ID"="IC"."CATEGORY_ID")
17 - filter(("OL"."ORDERED_ITEM"=NVL('101468',"OL"."ORDERED_ITEM") AND "OL"."UNIT_SELLING_PRICE"<>0))
18 - access("OL"."LINE_CATEGORY_CODE"='ORDER' AND "OL"."ACTUAL_SHIPMENT_DATE">=TO_DATE('2012-02-20 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
"OL"."ACTUAL_SHIPMENT_DATE"<=TO_DATE('2012-02-23 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
filter(("OL"."ACTUAL_SHIPMENT_DATE">=TO_DATE('2012-02-20 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND "OL"."LINE_CATEGORY_CODE"='ORDER'
AND "OL"."ACTUAL_SHIPMENT_DATE"<=TO_DATE('2012-02-23 00:00:00', 'yyyy-mm-dd hh24:mi:ss')))
20 - access("CUST"."CUST_ACCOUNT_ID"=)
26 - filter("SUSE"."SITE_USE_CODE"='SHIP_TO')
27 - access("SUSE"."SITE_USE_ID"=:B1)
28 - filter("ACCT_SITE"."ORG_ID"=142)
29 - access("SUSE"."CUST_ACCT_SITE_ID"="ACCT_SITE"."CUST_ACCT_SITE_ID")
31 - access("ACCT"."CUST_ACCOUNT_ID"="ACCT_SITE"."CUST_ACCOUNT_ID")
32 - access("P"."PARTY_ID"="ACCT"."PARTY_ID")
33 - filter(("ACCT"."PARTY_ID"="PARTY_SITE"."PARTY_ID" AND "P"."PARTY_ID"="PARTY_SITE"."PARTY_ID"))
34 - access("ACCT_SITE"."PARTY_SITE_ID"="PARTY_SITE"."PARTY_SITE_ID")
35 - access("LOC"."LOCATION_ID"="PARTY_SITE"."LOCATION_ID")
36 - filter(("OH"."ORG_ID"=142 AND "IC"."ORGANIZATION_ID"="OH"."SHIP_FROM_ORG_ID"))
37 - access("OH"."HEADER_ID"="OL"."HEADER_ID")
85 rows selected.Below plan for the above same query when i run from front end concurrent request it completed within an hour.
SQL> select * from table(dbms_xplan.display_cursor('1gnb26b0q2vxx',NULL,'ALLSTATS LAST'))
2 /
PLAN_TABLE_OUTPUT
SQL_ID 1gnb26b0q2vxx, child number 0
Plan hash value: 408306916
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
| 1 | HASH GROUP BY | | 1 | 1 | 2 |00:36:41.83 | 379M| | | |
| 2 | CONCATENATION | | 1 | | 71 |00:09:30.14 | 379M| | | |
|* 3 | FILTER | | 1 | | 0 |00:00:00.01 | 0 | | | |
| 4 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
| 5 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
|* 6 | HASH JOIN | | 0 | 4 | 0 |00:00:00.01 | 0 | 715K| 715K| |
| 7 | TABLE ACCESS BY INDEX ROWID | MTL_ITEM_CATEGORIES | 0 | 506 | 0 |00:00:00.01 | 0 | | | |
| 8 | NESTED LOOPS | | 0 | 26 | 0 |00:00:00.01 | 0 | | | |
| 9 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
| 10 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
| 11 | NESTED LOOPS | | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
|* 12 | TABLE ACCESS BY INDEX ROWID| FND_FLEX_VALUES | 0 | 22 | 0 |00:00:00.01 | 0 | | | |
|* 13 | INDEX RANGE SCAN | IDX$$_65860003 | 0 | 22 | 0 |00:00:00.01 | 0 | | | |
|* 14 | TABLE ACCESS BY INDEX ROWID| MTL_CATEGORIES_B | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
|* 15 | INDEX RANGE SCAN | MTL_CATEGORIES_B_N3 | 0 | 2 | 0 |00:00:00.01 | 0 | | | |
|* 16 | INDEX UNIQUE SCAN | FND_FLEX_VALUES_TL_U1 | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
|* 17 | INDEX UNIQUE SCAN | MTL_CATEGORIES_TL_U1 | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
|* 18 | INDEX RANGE SCAN | IDX$$_78250002 | 0 | 1528 | 0 |00:00:00.01 | 0 | | | |
|* 19 | TABLE ACCESS FULL | OE_ORDER_LINES_ALL | 0 | 97 | 0 |00:00:00.01 | 0 | | | |
|* 20 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_HEADERS_ALL | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
|* 21 | INDEX UNIQUE SCAN | OE_ORDER_HEADERS_U1 | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
| 22 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_ACCOUNTS | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
|* 23 | INDEX UNIQUE SCAN | HZ_CUST_ACCOUNTS_U1 | 0 | 1 | 0 |00:00:00.01 | 0 | | | |
| 24 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 34 | | | |
| 25 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 30 | | | |
| 26 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 24 | | | |
| 27 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 20 | | | |
| 28 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 14 | | | |
|* 29 | TABLE ACCESS BY INDEX ROWID| HZ_CUST_SITE_USES_ALL | 2 | 1 | 2 |00:00:00.01 | 8 | | | |
|* 30 | INDEX UNIQUE SCAN | HZ_CUST_SITE_USES_U1 | 2 | 1 | 2 |00:00:00.01 | 6 | | | |
|* 31 | TABLE ACCESS BY INDEX ROWID| HZ_CUST_ACCT_SITES_ALL | 2 | 9420 | 2 |00:00:00.01 | 6 | | | |
|* 32 | INDEX UNIQUE SCAN | HZ_CUST_ACCT_SITES_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
| 33 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_ACCOUNTS | 2 | 176K| 2 |00:00:00.01 | 6 | | | |
|* 34 | INDEX UNIQUE SCAN | HZ_CUST_ACCOUNTS_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
|* 35 | INDEX UNIQUE SCAN | HZ_PARTIES_U1 | 2 | 176K| 2 |00:00:00.01 | 4 | | | |
|* 36 | TABLE ACCESS BY INDEX ROWID | HZ_PARTY_SITES | 2 | 188K| 2 |00:00:00.01 | 6 | | | |
|* 37 | INDEX UNIQUE SCAN | HZ_PARTY_SITES_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
|* 38 | INDEX UNIQUE SCAN | HZ_LOCATIONS_U1 | 2 | 174K| 2 |00:00:00.01 | 4 | | | |
|* 39 | FILTER | | 1 | | 71 |00:09:30.14 | 379M| | | |
| 40 | NESTED LOOPS | | 1 | 1 | 71 |00:09:30.14 | 379M| | | |
| 41 | NESTED LOOPS | | 1 | 1 | 71 |00:09:30.11 | 379M| | | |
| 42 | NESTED LOOPS | | 1 | 18 | 16M|00:03:49.48 | 34M| | | |
| 43 | NESTED LOOPS | | 1 | 1 | 1075 |00:00:00.03 | 351 | | | |
| 44 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 9 | | | |
| 45 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 8 | | | |
| 46 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 6 | | | |
| 47 | TABLE ACCESS BY INDEX ROWID | FND_FLEX_VALUES | 1 | 1 | 1 |00:00:00.01 | 3 | | | |
|* 48 | INDEX RANGE SCAN | FND_FLEX_VALUES_N4 | 1 | 1 | 1 |00:00:00.01 | 2 | | | |
|* 49 | TABLE ACCESS BY INDEX ROWID | MTL_CATEGORIES_B | 1 | 1 | 1 |00:00:00.01 | 3 | | | |
|* 50 | INDEX RANGE SCAN | IDX$$_79530001 | 1 | 1 | 2 |00:00:00.01 | 1 | | | |
|* 51 | INDEX UNIQUE SCAN | FND_FLEX_VALUES_TL_U1 | 1 | 1 | 1 |00:00:00.01 | 2 | | | |
|* 52 | INDEX UNIQUE SCAN | MTL_CATEGORIES_TL_U1 | 1 | 1 | 1 |00:00:00.01 | 1 | | | |
| 53 | TABLE ACCESS BY INDEX ROWID | MTL_ITEM_CATEGORIES | 1 | 506 | 1075 |00:00:00.02 | 342 | | | |
|* 54 | INDEX RANGE SCAN | IDX$$_78250002 | 1 | 1528 | 1075 |00:00:00.01 | 5 | | | |
|* 55 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_HEADERS_ALL | 1075 | 6485 | 16M|00:12:38.97 | 34M| | | |
|* 56 | INDEX RANGE SCAN | OE_ORDER_HEADER_ALL_ORG_ID_NDX | 1075 | 141K| 394M|00:19:52.50 | 2141K| | | |
|* 57 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_LINES_ALL | 16M| 1 | 71 |00:23:47.72 | 345M| | | |
|* 58 | INDEX RANGE SCAN | OE_ORDER_LINES_N21 | 16M| 6 | 108M|00:08:35.98 | 32M| | | |
| 59 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_ACCOUNTS | 71 | 1 | 71 |00:00:00.01 | 247 | | | |
|* 60 | INDEX UNIQUE SCAN | HZ_CUST_ACCOUNTS_U1 | 71 | 1 | 71 |00:00:00.01 | 176 | | | |
| 61 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 34 | | | |
| 62 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 30 | | | |
| 63 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 24 | | | |
| 64 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 20 | | | |
| 65 | NESTED LOOPS | | 2 | 1 | 2 |00:00:00.01 | 14 | | | |
|* 66 | TABLE ACCESS BY INDEX ROWID| HZ_CUST_SITE_USES_ALL | 2 | 1 | 2 |00:00:00.01 | 8 | | | |
|* 67 | INDEX UNIQUE SCAN | HZ_CUST_SITE_USES_U1 | 2 | 1 | 2 |00:00:00.01 | 6 | | | |
|* 68 | TABLE ACCESS BY INDEX ROWID| HZ_CUST_ACCT_SITES_ALL | 2 | 9420 | 2 |00:00:00.01 | 6 | | | |
|* 69 | INDEX UNIQUE SCAN | HZ_CUST_ACCT_SITES_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
| 70 | TABLE ACCESS BY INDEX ROWID | HZ_CUST_ACCOUNTS | 2 | 176K| 2 |00:00:00.01 | 6 | | | |
|* 71 | INDEX UNIQUE SCAN | HZ_CUST_ACCOUNTS_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
|* 72 | INDEX UNIQUE SCAN | HZ_PARTIES_U1 | 2 | 176K| 2 |00:00:00.01 | 4 | | | |
|* 73 | TABLE ACCESS BY INDEX ROWID | HZ_PARTY_SITES | 2 | 188K| 2 |00:00:00.01 | 6 | | | |
|* 74 | INDEX UNIQUE SCAN | HZ_PARTY_SITES_U1 | 2 | 1 | 2 |00:00:00.01 | 4 | | | |
|* 75 | INDEX UNIQUE SCAN | HZ_LOCATIONS_U1 | 2 | 174K| 2 |00:00:00.01 | 4 | | | |
Predicate Information (identified by operation id):
3 - filter((:P_FROM_DATE<=:P_TO_DATE AND :P_BUSINESS_UNIT IS NULL))
6 - access("IC"."INVENTORY_ITEM_ID"="OL"."INVENTORY_ITEM_ID")
12 - filter("B"."FLEX_VALUE" IS NOT NULL)
13 - access("B"."FLEX_VALUE_SET_ID"=1012990)
14 - filter("B"."STRUCTURE_ID"=50289)
15 - access("B"."SEGMENT3"="B"."FLEX_VALUE")
filter("B"."SEGMENT3" IS NOT NULL)
16 - access("B"."FLEX_VALUE_ID"="T"."FLEX_VALUE_ID" AND "T"."LANGUAGE"=USERENV('LANG'))
17 - access("B"."CATEGORY_ID"="T"."CATEGORY_ID" AND "T"."LANGUAGE"=USERENV('LANG'))
18 - access("B"."CATEGORY_ID"="IC"."CATEGORY_ID")
19 - filter(("OL"."ACTUAL_SHIPMENT_DATE">=:P_FROM_DATE AND "OL"."ACTUAL_SHIPMENT_DATE"<=:P_TO_DATE AND
"OL"."ORDERED_ITEM"=NVL(:ITEM_HIGH,"OL"."ORDERED_ITEM") AND "OL"."LINE_CATEGORY_CODE"='ORDER' AND "OL"."UNIT_SELLING_PRICE"<>0))
20 - filter(("OH"."ORG_ID"=:P_ORG_ID AND "IC"."ORGANIZATION_ID"="OH"."SHIP_FROM_ORG_ID"))
21 - access("OH"."HEADER_ID"="OL"."HEADER_ID")
23 - access("CUST"."CUST_ACCOUNT_ID"=)
29 - filter("SUSE"."SITE_USE_CODE"='SHIP_TO')
30 - access("SUSE"."SITE_USE_ID"=:B1)
31 - filter("ACCT_SITE"."ORG_ID"=:P_ORG_ID)
32 - access("SUSE"."CUST_ACCT_SITE_ID"="ACCT_SITE"."CUST_ACCT_SITE_ID")
34 - access("ACCT"."CUST_ACCOUNT_ID"="ACCT_SITE"."CUST_ACCOUNT_ID")
35 - access("P"."PARTY_ID"="ACCT"."PARTY_ID")
36 - filter(("ACCT"."PARTY_ID"="PARTY_SITE"."PARTY_ID" AND "P"."PARTY_ID"="PARTY_SITE"."PARTY_ID"))
37 - access("ACCT_SITE"."PARTY_SITE_ID"="PARTY_SITE"."PARTY_SITE_ID")
38 - access("LOC"."LOCATION_ID"="PARTY_SITE"."LOCATION_ID")
39 - filter((:P_FROM_DATE<=:P_TO_DATE AND :P_BUSINESS_UNIT IS NOT NULL))
48 - access("B"."FLEX_VALUE"=:P_BUSINESS_UNIT AND "B"."FLEX_VALUE_SET_ID"=1012990)
49 - filter("B"."STRUCTURE_ID"=50289)
50 - access("B"."SEGMENT3"="B"."FLEX_VALUE")
filter("B"."SEGMENT3" IS NOT NULL)
51 - access("B"."FLEX_VALUE_ID"="T"."FLEX_VALUE_ID" AND "T"."LANGUAGE"=USERENV('LANG'))
52 - access("B"."CATEGORY_ID"="T"."CATEGORY_ID" AND "T"."LANGUAGE"=USERENV('LANG'))
54 - access("B"."CATEGORY_ID"="IC"."CATEGORY_ID")
55 - filter("IC"."ORGANIZATION_ID"="OH"."SHIP_FROM_ORG_ID")
56 - access("OH"."ORG_ID"=:P_ORG_ID)
57 - filter(("OL"."ACTUAL_SHIPMENT_DATE">=:P_FROM_DATE AND "OL"."ACTUAL_SHIPMENT_DATE"<=:P_TO_DATE AND
"OL"."ORDERED_ITEM"=NVL(:ITEM_HIGH,"OL"."ORDERED_ITEM") AND "OL"."LINE_CATEGORY_CODE"='ORDER' AND "OL"."UNIT_SELLING_PRICE"<>0 AND
"IC"."INVENTORY_ITEM_ID"="OL"."INVENTORY_ITEM_ID"))
58 - access("OH"."HEADER_ID"="OL"."HEADER_ID")
60 - access("CUST"."CUST_ACCOUNT_ID"=)
66 - filter("SUSE"."SITE_USE_CODE"='SHIP_TO')
67 - access("SUSE"."SITE_USE_ID"=:B1)
68 - filter("ACCT_SITE"."ORG_ID"=:P_ORG_ID)
69 - access("SUSE"."CUST_ACCT_SITE_ID"="ACCT_SITE"."CUST_ACCT_SITE_ID")
71 - access("ACCT"."CUST_ACCOUNT_ID"="ACCT_SITE"."CUST_ACCOUNT_ID")
72 - access("P"."PARTY_ID"="ACCT"."PARTY_ID")
73 - filter(("ACCT"."PARTY_ID"="PARTY_SITE"."PARTY_ID" AND "P"."PARTY_ID"="PARTY_SITE"."PARTY_ID"))
74 - access("ACCT_SITE"."PARTY_SITE_ID"="PARTY_SITE"."PARTY_SITE_ID")
75 - access("LOC"."LOCATION_ID"="PARTY_SITE"."LOCATION_ID")
145 rows selected.one thing looking strange at predicate section at line 23 and 60 access("CUST"."CUST_ACCOUNT_ID"=),Plan is also differing why?Just look at filter predicates 3 and 39 which I highlighted previously.
With a query using bind variable, p_business_unit might be supplied with a null value and therefore two possible paths exist in the CONCATENTATION plan to cope with those possibilities (and the possibility that P_FROM_DATE is not <= P_TO_DATE).
If instead of using bind variable you supply a literal - i.e. '101468' - then the optimizer doesn't not have to worry about the fact that '101468' might be null. As far as this piece of SQL is concerned, it's a constant.
Therefore you shouldn't compare SQL that runs with binds with SQl that runs with literals, particularly where the sql involves conditional predicates.
To use a simplification, consider the difference here:
SQL> explain plan for
2 select 1 from dual where 1 = nvl(1,1);
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 1388734953
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
8 rows selected.
SQL> explain plan for
2 select 1 from dual where 1 = nvl(:1,1);
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 4034615273
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | |
| 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter(NVL(:1,1)=1)
14 rows selected.Furthermore, to emphasis my point about substition variables (&variable_name) consider this:
SQL> explain plan for
2 select 1 from dual where 1 = nvl(&1,1);
Enter value for 1: 1
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 1388734953
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 |
| 1 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
8 rows selected.
SQL> Does the substitution variable behave like a bind variable or like a literal?
A literal, because that's what it is. Substituted in before the statement is sent to the database and parsed. -
Cost in explain plan vs elapsed time
hi gurus,
i have two tables with identical data volume(same database/schema/tablespace) and the only difference between these two is, one partitioned on a date filed.
statistics are up to date.
same query is executed against both tables, no partition pruning involved.
select ....... from non-partitioned
execution plan cost=92
elapsed time=117612
select ... from partitioned
execution plan cost=3606
elapsed time=19559
though plan cost of query against non-partitioned is quite less than partitioned, elapsed time in v$sqlarea is higher than partitioned.
what could be the reason please?
thanks,
charles
Edited by: user570138 on May 6, 2010 6:54 AMuser570138 wrote:
if elapsed time value is very volatile(with the difference in explain plan cost) , then how can i compare the performance of the query?Note that the same query with same execution plan and same data can provide different execution times - and due to a number of factors. The primary one being that the first time the query is executed, it performs physical I/O and loads the data into the buffer cache - where the same subsequent query finds this data via cheaper and faster logical I/O in the cache.
in my case i want to compare the performance change before and after table partitioning.Then look at the actual utilisation cost of the query and not (variant) elapsed execution time. The most expensive operation on a db platform is typically I/O. The more I/O, the slower the execution time.
I/O can be decreased in a number of ways. The usual approach in the database environment is to provide better or alternative data structures, in order to create more optimal I/O paths.
So instead of using a hash table and separate PK b+tree index, using an index organised table. Instead of a single large table with indexes, a partitioned table with local indexes. Instead of joining plain tables, joining tables that have been clustered. Etc.
In most cases, when done correctly, these physical data structure changes do not even impact the application layer. The SQL and code in this layer should be blissfully unaware of the physical structure changes done to improve performance.
Likewise, changes in the logical layer (data model changes) can also improve performance. This of course does impact the application layer - and requires a proper design and implementation in the physical layer. Often proper data modeling is overlooked and flaws in it is attempted to be fixed by hacking the physical layer.
my aim is to measure the query performance improvements, if any, by partitioning an existing tableWhy not measure current I/O before an operation, and then after the operation - and use the difference to determine the amount of I/O performed by that operation?
This can be implemented in a start/stop watch fashion (instead of measuring time, measuring I/O) using the v$sesstat virtual performance view. -
Oracle Hint not causing any change to explain plan
Hi,
I was facing a problem about ORA-00600 for using Connect by Prior query,
details of which are at -
Connect by Prior - ORA-00600: internal error code, arguments: [kkqcbydrv:1
As is documented by Oracle, workaround for this is to use /*+ NO_UNNEST */ in query.
I displayed the explain plan for original query and after putting hint in query.
There is no difference in the explain plans, I am a starter for explain plans and don't know much of it.
But shouldn't the hint cause some change in explain plan?
Even the hash values as mentioned in explain plans are same.
Thanks in advance.
Av.Perhaps it would help if you put the query (with the hint) and the explain plan here.
-
Sub Partitioning does not have considerable impact Explain Plan
Hi Guys,
I have a table that is list - list sub partitioned on Oracle 11g - 11.2.0.3.
The first partition is on the CIRCLE_ID column and the second sub partition is on the LOAD_DTTM.
Now i have tried 2 queries on the database
1 - select MOBILENUMBER, CLOSING_BAL from GSM_PRR_SUM a1
where A1.CIRCLE_ID ='AK'
AND a1.LOAD_DTTM BETWEEN '28-MAR-2012' AND '03-APR-2012';
2 - select MOBILENUMBER, CLOSING_BAL from GSM_PRR_SUM a1
where A1.CIRCLE_ID ='AK'
AND to_char(a1.LOAD_DTTM) like '%MAR%'
Ideally the 2nd query should take a much higher time than the first query.
But the explain plan shows a difference of less than 1%.
Can you pls provide some insights as why Oracle is not understanding that subpartitioning will be faster?
Thanks,
ManishHi Dom
Thanks for your reply.
Is the first query using partition pruning? - Yes
Have you gathered stats, etc, etc? - No. All our queries always need to access the entire table and not a particular subset and the where criteria always uses partition and sub partition columns. so we dont see the need to collect stats. Can you pls advise what stats need to be collected and what will be the advantage of those?
Below are the output of the Explain Plan and Trace Output -
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> show parameter optimizer;
NAME TYPE VALUE
optimizer_capture_sql_plan_baselines boolean FALSE
optimizer_dynamic_sampling integer 2
optimizer_features_enable string 11.2.0.3
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100
optimizer_mode string ALL_ROWS
optimizer_secure_view_merging boolean TRUE
optimizer_use_invisible_indexes boolean FALSE
optimizer_use_pending_statistics boolean FALSE
optimizer_use_sql_plan_baselines boolean TRUE
SQL> show parameter db_file_multi;
NAME TYPE VALUE
db_file_multiblock_read_count integer 128
SQL> show parameter cursor_sharing
NAME TYPE VALUE
cursor_sharing string EXACT
SQL> column sname format a20
SQL> column pname foramt 20
SP2-0158: unknown COLUMN option "foramt"
SQL> column pname format a20
SQL> column pval2 format a20
SQL> select
2 sname
3 , pname
4 , pval1
5 ,pval2
6 from sys.aux_stats$;
from sys.aux_stats$
ERROR at line 6:
ORA-00942: table or view does not exist
SQL> explain plan for
select MOBILENUMBER, CLOSING_BAL from GSM_PRR_SUM_NEW a1
where A1.CIRCLE_ID ='KA'
AND a1.LOAD_DTTM BETWEEN '28-MAR-2012' AND '03-APR-2012'
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
Plan hash value: 3032220315
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)
| Time | Pstart| Pstop |
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 41M| 1643M| 548M(100)
|999:59:59 | | |
| 1 | PARTITION LIST SINGLE | | 41M| 1643M| 548M(100)
|999:59:59 | KEY | KEY |
| 2 | PARTITION LIST ITERATOR| | 41M| 1643M| 548M(100)
|999:59:59 | KEY | KEY |
| 3 | TABLE ACCESS FULL | GSM_PRR_SUM_NEW | 41M| 1643M| 548M(100)
|999:59:59 | KEY | KEY |
PLAN_TABLE_OUTPUT
Note
- dynamic sampling used for this statement (level=2)
14 rows selected.
SQL> explain plan for
select MOBILENUMBER, CLOSING_BAL from GSM_PRR_SUM_NEW a1
where A1.CIRCLE_ID ='KA'
AND to_char(a1.LOAD_DTTM) like '%MAR%';
2 3 4
Explained.
SQL> SQL> SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
Plan hash value: 189546713
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T
ime | Pstart| Pstop |
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 62M| 2521M| 5435M(100)|99
9:59:59 | | |
| 1 | PARTITION LIST SINGLE| | 62M| 2521M| 5435M(100)|99
9:59:59 | KEY | KEY |
| 2 | PARTITION LIST ALL | | 62M| 2521M| 5435M(100)|99
9:59:59 | 1 | 305 |
|* 3 | TABLE ACCESS FULL | GSM_PRR_SUM_NEW | 62M| 2521M| 5435M(100)|99
9:59:59 | KEY | KEY |
PLAN_TABLE_OUTPUT
Predicate Information (identified by operation id):
3 - filter(TO_CHAR(INTERNAL_FUNCTION("A1"."LOAD_DTTM")) LIKE '%MAR%')
Note
PLAN_TABLE_OUTPUT
- dynamic sampling used for this statement (level=2)
19 rows selected.
SQL>
SQL> SET AUTOTRACE TRACEONLY ARRAYSIZE 100
SQL> select MOBILENUMBER, CLOSING_BAL from GSM_PRR_SUM_NEW a1
where A1.CIRCLE_ID ='KA'
AND a1.LOAD_DTTM BETWEEN '28-MAR-2012' AND '03-APR-2012' 2 3 ;
49637012 rows selected.
Execution Plan
Plan hash value: 3032220315
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)
| Time | Pstart| Pstop |
| 0 | SELECT STATEMENT | | 41M| 1643M| 546M(100)
|999:59:59 | | |
| 1 | PARTITION LIST SINGLE | | 41M| 1643M| 546M(100)
|999:59:59 | KEY | KEY |
| 2 | PARTITION LIST ITERATOR| | 41M| 1643M| 546M(100)
|999:59:59 | KEY | KEY |
| 3 | TABLE ACCESS FULL | GSM_PRR_SUM_NEW | 41M| 1643M| 546M(100)
|999:59:59 | KEY | KEY |
Note
- dynamic sampling used for this statement (level=2)
Statistics
0 recursive calls
7 db block gets
530220 consistent gets
33636 physical reads
0 redo size
644311477 bytes sent via SQL*Net to client
5460594 bytes received via SQL*Net from client
496372 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
49637012 rows processed
SQL> SET AUTOTRACE TRACEONLY ARRAYSIZE 100
SQL> select MOBILENUMBER, CLOSING_BAL from GSM_PRR_SUM_NEW a1
where A1.CIRCLE_ID ='KA'
AND to_char(a1.LOAD_DTTM) like '%MAR%' 2 3
4 ;
219166976 rows selected.
Execution Plan
Plan hash value: 189546713
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T
ime | Pstart| Pstop |
| 0 | SELECT STATEMENT | | 228M| 9155M| 3552M(100)|99
9:59:59 | | |
| 1 | PARTITION LIST SINGLE| | 228M| 9155M| 3552M(100)|99
9:59:59 | KEY | KEY |
| 2 | PARTITION LIST ALL | | 228M| 9155M| 3552M(100)|99
9:59:59 | 1 | 274 |
|* 3 | TABLE ACCESS FULL | GSM_PRR_SUM_NEW | 228M| 9155M| 3552M(100)|99
9:59:59 | KEY | KEY |
Predicate Information (identified by operation id):
3 - filter(TO_CHAR(INTERNAL_FUNCTION("A1"."LOAD_DTTM")) LIKE '%MAR%')
Note
- dynamic sampling used for this statement (level=2)
Statistics
38 recursive calls
107 db block gets
2667792 consistent gets
561765 physical reads
0 redo size
2841422984 bytes sent via SQL*Net to client
24108883 bytes received via SQL*Net from client
2191671 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
219166976 rows processed
SQL>
Thanks,
Manish -
Explain plan changes by result size from contains clause
I use 10.2.0.3 Std Edition and have a query like this
select t1.id from table1 t1
where t1.col99 = 123
and t1.id in (select ttxt.id from fulltexttable ttxt where contains (ttxt.thetext, 'word1 & word2'));
(note: for each row in table1 exists at least one corresponding row in fulltexttable)
Now I came across a surprising change in execution plans depending on the values of word1 and word2:
- if the number of result rows from the subquery is low compared to all rows the full text index is used (table access by rowid/domain index)
- if the number of result rows is high explain plan does not indicate any use of the domain index (full text index) but only a full text table scan. And the slow execution proves this plan.
But: if I create explain plan for the subquery only there is no difference whether the number of result rows is high or low: the full text index is always used.
Any clue for this change in execution strategy?
Michaelhi michael,
this is expected behaviour. because you have a query incorporating more than just a text-index, and furthermore, multiple tables, the optimizer may choose different access paths according to the cardinality of your where clause terms. in fact, anything you see is actually vanilla behaviour.
however, as i suppose, you probably have not yet heard about the "post filter" characteristic of a context index. see the tuning chapter of the text dev guide for more info. also note that the optimizer has no other way than accessing the context index directly iff you execute the subquery on its own (the "post filter" characteristic is not applicable here, because a post filter always needs some input to be filtered). and finally, be aware that oracle may unnest your subquery by its own decision, that is, do not try to force a direct context index access by a subquery, it will not work (a compiler hint is the only thing that works relyably).
the only thing i can not follow is the fts for your second example. dont you have join indexes on table1.id and fulltexttable.id, respectively?
p -
Differenet Explain Plan for Same Query
DB Version : 11.2.0.3
OS Version : AIX 6
I have two Queries ( The Difference between Them Only 940 and 584 ) When I Generate Explain Plan Different Output Why ? Why CPU time is Different Each Time
First Query Statement :
INSERT INTO TempSearchResult (t_aid,
t_umidl,
t_umidh,
X_CREA_DATE_TIME_MESG)
SELECT z.aid,
z.mesg_s_umidl,
z.mesg_s_umidh,
z.mesg_crea_date_time
FROM ( SELECT m.aid,
m.mesg_s_umidl,
m.mesg_s_umidh,
m.mesg_crea_date_time
FROM RSMESG_ESIDE m
WHERE 1 = 1
AND m.mesg_crea_date_time BETWEEN TO_DATE (
'20120131 10:00:00',
'YYYYMMDD HH24:MI:SS')
AND TO_DATE (
'20120131 13:00:00',
'YYYYMMDD HH24:MI:SS')
AND m.mesg_frmt_name = 'Swift'
AND m.mesg_sender_x1 = 'SOGEFRPPXXX'
AND m.mesg_nature = 'FINANCIAL_MSG'
AND m.mesg_type LIKE '950'
ORDER BY mesg_crea_date_time) z
WHERE ROWNUM <= 5000
Explain Plan for First Query :
PLAN_TABLE_OUTPUT
Plan hash value: 3901722890
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
| 0 | INSERT STATEMENT | | 2866 | 134K| 197 (3)| 00:00:03 | | |
| 1 | LOAD TABLE CONVENTIONAL | TEMPSEARCHRESULT | | | | | | |
|* 2 | COUNT STOPKEY | | | | | | | |
| 3 | VIEW | | 2866 | 134K| 197 (3)| 00:00:03 | | |
|* 4 | SORT ORDER BY STOPKEY | | 2866 | 333K| 197 (3)| 00:00:03 | | |
| 5 | NESTED LOOPS | | 2866 | 333K| 196 (2)| 00:00:03 | | |
PLAN_TABLE_OUTPUT
| 6 | NESTED LOOPS | | 1419 | 148K| 196 (2)| 00:00:03 | | |
|* 7 | HASH JOIN | | 1419 | 141K| 196 (2)| 00:00:03 | | |
| 8 | NESTED LOOPS | | 91 | 1911 | 2 (0)| 00:00:01 | | |
| 9 | TABLE ACCESS BY INDEX ROWID | SUSER | 1 | 10 | 1 (0)| 00:00:01 | | |
|* 10 | INDEX UNIQUE SCAN | IX_SUSER | 1 | | 0 (0)| 00:00:01 | | |
|* 11 | INDEX FULL SCAN | PK_SUNITUSERGROUP | 91 | 1001 | 1 (0)| 00:00:01 | | |
| 12 | PARTITION RANGE SINGLE | | 1450 | 114K| 193 (2)| 00:00:03 | 2 | 2 |
|* 13 | TABLE ACCESS BY LOCAL INDEX ROWID| RMESG | 1450 | 114K| 193 (2)| 00:00:03 | 2 | 2 |
|* 14 | INDEX SKIP SCAN | IX_RMESG | 415 | | 14 (15)| 00:00:01 | 2 | 2 |
|* 15 | INDEX UNIQUE SCAN | PK_SMSGUSERGROUP | 1 | 5 | 0 (0)| 00:00:01 | | |
|* 16 | INDEX UNIQUE SCAN | PK_SBICUSERGROUP | 2 | 24 | 0 (0)| 00:00:01 | | |
PLAN_TABLE_OUTPUT
PLAN_TABLE_OUTPUT
Predicate Information (identified by operation id):
2 - filter(ROWNUM<=5000)
4 - filter(ROWNUM<=5000)
7 - access("X_INST0_UNIT_NAME"="UNIT")
10 - access("SUSER"."USERNAME"="SIDE"."GETMYUSER"())
11 - access("SUSER"."GROUPID"="SUNITUSERGROUP"."GROUPID")
filter("SUSER"."GROUPID"="SUNITUSERGROUP"."GROUPID")
PLAN_TABLE_OUTPUT
13 - filter("RMESG"."MESG_SENDER_X1"='SOGEFRPPXXX' AND "RMESG"."MESG_NATURE"='FINANCIAL_MSG' AND
"RMESG"."MESG_FRMT_NAME"='Swift')
14 - access("RMESG"."MESG_CREA_DATE_TIME">=TO_DATE(' 2012-01-31 10:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"RMESG"."MESG_TYPE"='950' AND "RMESG"."MESG_CREA_DATE_TIME"<=TO_DATE(' 2012-01-31 13:00:00', 'syyyy-mm-dd hh24:mi:ss'))
filter("RMESG"."MESG_TYPE"='950')
15 - access("X_CATEGORY"="CATEGORY" AND "SUSER"."GROUPID"="SMSGUSERGROUP"."GROUPID")
16 - access("X_OWN_LT"="BICCODE" AND "SUSER"."GROUPID"="SBICUSERGROUP"."GROUPID")
40 rows selected.
Second query
INSERT INTO TempSearchResult (t_aid,
t_umidl,
t_umidh,
X_CREA_DATE_TIME_MESG)
SELECT z.aid,
z.mesg_s_umidl,
z.mesg_s_umidh,
z.mesg_crea_date_time
FROM ( SELECT m.aid,
m.mesg_s_umidl,
m.mesg_s_umidh,
m.mesg_crea_date_time
FROM RSMESG_ESIDE m
WHERE 1 = 1
AND m.mesg_crea_date_time BETWEEN TO_DATE (
'20120117 10:00:00',
'YYYYMMDD HH24:MI:SS')
AND TO_DATE (
'20120117 13:00:00',
'YYYYMMDD HH24:MI:SS')
AND m.mesg_frmt_name = 'Swift'
AND m.mesg_sender_x1 = 'SOGEFRPPGSS'
AND m.mesg_nature = 'FINANCIAL_MSG'
AND m.mesg_type LIKE '548'
ORDER BY mesg_crea_date_time) z
WHERE ROWNUM <= 5000
Explain Plan For Second Query :
PLAN_TABLE_OUTPUT
Plan hash value: 4106071428
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
| 0 | INSERT STATEMENT | | 1073 | 51504 | | 2622 (1)| 00:00:32 | | |
| 1 | LOAD TABLE CONVENTIONAL | TEMPSEARCHRESULT | | | | | | | |
|* 2 | COUNT STOPKEY | | | | | | | | |
| 3 | VIEW | | 1073 | 51504 | | 2622 (1)| 00:00:32 | | |
|* 4 | SORT ORDER BY STOPKEY | | 1073 | 124K| | 2622 (1)| 00:00:32 | | |
| 5 | NESTED LOOPS | | 1073 | 124K| | 2621 (1)| 00:00:32 | | |
PLAN_TABLE_OUTPUT
| 6 | NESTED LOOPS | | 531 | 56817 | | 2621 (1)| 00:00:32 | | |
| 7 | NESTED LOOPS | | 531 | 54162 | | 2621 (1)| 00:00:32 | | |
| 8 | NESTED LOOPS | | 543 | 49413 | | 2621 (1)| 00:00:32 | | |
| 9 | TABLE ACCESS BY INDEX ROWID | SUSER | 1 | 10 | | 1 (0)| 00:00:01 | | |
|* 10 | INDEX UNIQUE SCAN | IX_SUSER | 1 | | | 0 (0)| 00:00:01 | | |
| 11 | PARTITION RANGE SINGLE | | 543 | 43983 | | 2621 (1)| 00:00:32 | 2 | 2 |
|* 12 | TABLE ACCESS BY LOCAL INDEX ROWID| RMESG | 543 | 43983 | | 2621 (1)| 00:00:32 | 2 | 2 |
| 13 | BITMAP CONVERSION TO ROWIDS | | | | | | | | |
| 14 | BITMAP AND | | | | | | | | |
| 15 | BITMAP CONVERSION FROM ROWIDS | | | | | | | | |
|* 16 | INDEX RANGE SCAN | IX_SENDER | 25070 | | | 894 (1)| 00:00:11 | 2 | 2 |
PLAN_TABLE_OUTPUT
| 17 | BITMAP CONVERSION FROM ROWIDS | | | | | | | | |
| 18 | SORT ORDER BY | | | | 408K| | | | |
|* 19 | INDEX RANGE SCAN | IX_RMESG | 25070 | | | 1405 (1)| 00:00:17 | 2 | 2 |
|* 20 | INDEX UNIQUE SCAN | PK_SUNITUSERGROUP | 1 | 11 | | 0 (0)| 00:00:01 | | |
|* 21 | INDEX UNIQUE SCAN | PK_SMSGUSERGROUP | 1 | 5 | | 0 (0)| 00:00:01 | | |
|* 22 | INDEX UNIQUE SCAN | PK_SBICUSERGROUP | 2 | 24 | | 0 (0)| 00:00:01 | | |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
2 - filter(ROWNUM<=5000)
4 - filter(ROWNUM<=5000)
10 - access("SUSER"."USERNAME"="SIDE"."GETMYUSER"())
12 - filter("RMESG"."MESG_NATURE"='FINANCIAL_MSG' AND "RMESG"."MESG_FRMT_NAME"='Swift')
16 - access("RMESG"."MESG_SENDER_X1"='SOGEFRPPGSS')
19 - access("RMESG"."MESG_CREA_DATE_TIME">=TO_DATE(' 2012-01-17 10:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"RMESG"."MESG_TYPE"='548' AND "RMESG"."MESG_CREA_DATE_TIME"<=TO_DATE(' 2012-01-17 13:00:00', 'syyyy-mm-dd hh24:mi:ss'))
filter("RMESG"."MESG_TYPE"='548' AND "RMESG"."MESG_CREA_DATE_TIME"<=TO_DATE(' 2012-01-17 13:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "RMESG"."MESG_CREA_DATE_TIME">=TO_DATE(' 2012-01-17 10:00:00', 'syyyy-mm-dd hh24:mi:ss'))
20 - access("X_INST0_UNIT_NAME"="UNIT" AND "SUSER"."GROUPID"="SUNITUSERGROUP"."GROUPID")
21 - access("X_CATEGORY"="CATEGORY" AND "SUSER"."GROUPID"="SMSGUSERGROUP"."GROUPID")
PLAN_TABLE_OUTPUT
22 - access("X_OWN_LT"="BICCODE" AND "SUSER"."GROUPID"="SBICUSERGROUP"."GROUPID")
45 rows selected.
Table Structure TEMPSEARCHRESULT
CREATE GLOBAL TEMPORARY TABLE TEMPSEARCHRESULT
T_AID NUMBER(3),
T_UMIDL NUMBER(10),
T_UMIDH NUMBER(10),
X_CREA_DATE_TIME_MESG DATE
ON COMMIT PRESERVE ROWS
NOCACHE;
CREATE INDEX SIDE.TEMP_SEARCH_INDEX ON SIDE.TEMPSEARCHRESULT
(T_AID, T_UMIDL, T_UMIDH, X_CREA_DATE_TIME_MESG);Again Thank you For your amazing Answer.
For indexes it's a balance. Check this query which is Simple
Select * from RMESGI generated Explain Plan for it to see effect of indexes .
PLAN_TABLE_OUTPUT
Plan hash value: 1686435785
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
| 0 | SELECT STATEMENT | | 11M| 8920M| 376K (1)| 01:15:20 | | |
| 1 | PARTITION RANGE ALL| | 11M| 8920M| 376K (1)| 01:15:20 | 1 | 12 |
| 2 | TABLE ACCESS FULL | RMESG | 11M| 8920M| 376K (1)| 01:15:20 | 1 | 12 |
---------------------------------------------------------------------------------------------1:15:20 For table access and Full Scan Also , I generate new Indexes on the table like the following
CREATE TABLE RMESG(
aid NUMBER(3) NOT NULL,
mesg_s_umidl NUMBER(10) NOT NULL,
mesg_s_umidh NUMBER(10) NOT NULL,
mesg_validation_requested CHAR(18) NOT NULL,
mesg_validation_passed CHAR(18) NOT NULL,
mesg_class CHAR(16) NOT NULL,
mesg_is_text_readonly NUMBER(1) NOT NULL,
mesg_is_delete_inhibited NUMBER(1) NOT NULL,
mesg_is_text_modified NUMBER(1) NOT NULL,
mesg_is_partial NUMBER(1) NOT NULL,
mesg_crea_mpfn_name CHAR(24) NOT NULL,
mesg_crea_rp_name CHAR(24) NOT NULL,
mesg_crea_oper_nickname CHAR(151) NOT NULL,
mesg_crea_date_time DATE NOT NULL,
mesg_mod_oper_nickname CHAR(151) NOT NULL,
mesg_mod_date_time DATE NOT NULL,
mesg_frmt_name VARCHAR2(17) NOT NULL,
mesg_nature CHAR(14) NOT NULL,
mesg_sender_x1 CHAR(11) NOT NULL,
mesg_sender_corr_type VARCHAR2(24) NOT NULL,
mesg_uumid VARCHAR2(50) NOT NULL,
mesg_uumid_suffix NUMBER(10) NOT NULL,
x_own_lt CHAR(8) NOT NULL,
x_inst0_unit_name VARCHAR2(32) default 'NONE' NOT NULL,
x_category CHAR(1) NOT NULL,
archived NUMBER(1) NOT NULL,
restored NUMBER(1) NOT NULL,
mesg_related_s_umid CHAR(16) NULL,
mesg_status CHAR(12) NULL,
mesg_crea_appl_serv_name CHAR(24) NULL,
mesg_verf_oper_nickname CHAR(151) NULL,
mesg_data_last NUMBER(10) NULL,
mesg_token NUMBER(10) NULL,
mesg_batch_reference VARCHAR2(46) NULL,
mesg_cas_sender_reference VARCHAR2(40) NULL,
mesg_cas_target_rp_name VARCHAR2(20) NULL,
mesg_ccy_amount VARCHAR2(501) NULL,
mesg_copy_service_id VARCHAR2(4) NULL,
mesg_data_keyword1 VARCHAR2(80) NULL,
mesg_data_keyword2 VARCHAR2(80) NULL,
mesg_data_keyword3 VARCHAR2(80) NULL,
mesg_delv_overdue_warn_req NUMBER(1) NULL,
mesg_fin_ccy_amount VARCHAR2(24) NULL,
mesg_fin_value_date CHAR(6) NULL,
mesg_is_live NUMBER(1) NULL,
mesg_is_retrieved NUMBER(1) NULL,
mesg_mesg_user_group VARCHAR2(24) NULL,
mesg_network_appl_ind CHAR(3) NULL,
mesg_network_delv_notif_req NUMBER(1) NULL,
mesg_network_obso_period NUMBER(10) NULL,
mesg_network_priority CHAR(12) NULL,
mesg_possible_dup_creation VARCHAR2(8) NULL,
mesg_receiver_alia_name VARCHAR2(32) NULL,
mesg_receiver_swift_address CHAR(12) NULL,
mesg_recovery_accept_info VARCHAR2(80) NULL,
mesg_rel_trn_ref VARCHAR2(80) NULL,
mesg_release_info VARCHAR2(32) NULL,
mesg_security_iapp_name VARCHAR2(80) NULL,
mesg_security_required NUMBER(1) NULL,
mesg_sender_x2 VARCHAR2(21) NULL,
mesg_sender_x3 VARCHAR2(21) NULL,
mesg_sender_x4 VARCHAR2(21) NULL,
mesg_sender_branch_info VARCHAR2(71) NULL,
mesg_sender_city_name VARCHAR2(36) NULL,
mesg_sender_ctry_code VARCHAR2(3) NULL,
mesg_sender_ctry_name VARCHAR2(71) NULL,
mesg_sender_institution_name VARCHAR2(106) NULL,
mesg_sender_location VARCHAR2(106) NULL,
mesg_sender_swift_address CHAR(12) NULL,
mesg_sub_format VARCHAR2(6) NULL,
mesg_syntax_table_ver VARCHAR2(8) NULL,
mesg_template_name VARCHAR2(32) NULL,
mesg_trn_ref VARCHAR2(16) NULL,
mesg_type CHAR(3) NULL,
mesg_user_issued_as_pde NUMBER(1) NULL,
mesg_user_priority_code CHAR(4) NULL,
mesg_user_reference_text VARCHAR2(30) NULL,
mesg_zz41_is_possible_dup NUMBER(1) NULL,
x_fin_ccy CHAR(3) NULL,
x_fin_amount NUMBER(21,4) NULL,
x_fin_value_date DATE NULL,
x_fin_ocmt_ccy CHAR(3) NULL,
x_fin_ocmt_amount NUMBER(21,4) NULL,
x_receiver_x1 CHAR(11) NULL,
x_receiver_x2 VARCHAR2(21) NULL,
x_receiver_x3 VARCHAR2(21) NULL,
x_receiver_x4 VARCHAR2(21) NULL,
last_update DATE NULL,
set_id NUMBER(10) NULL,
mesg_requestor_dn VARCHAR2(101) NULL,
mesg_service VARCHAR2(31) NULL,
mesg_request_type VARCHAR2(31) NULL,
mesg_identifier VARCHAR2(31) NULL,
mesg_xml_query_ref1 VARCHAR2(101) NULL,
mesg_xml_query_ref2 VARCHAR2(101) NULL,
mesg_xml_query_ref3 VARCHAR2(101) NULL,
mesg_appl_sender_reference VARCHAR2(51) NULL,
mesg_payload_type VARCHAR2(31) NULL,
mesg_sign_digest_reference VARCHAR2(41) NULL,
mesg_sign_digest_value VARCHAR2(51) NULL,
mesg_use_pki_signature NUMBER(1) NULL
PARTITION BY RANGE(MESG_CREA_DATE_TIME) (
PARTITION SIDE_MIN VALUES LESS THAN (TO_DATE(20000101, 'YYYYMMDD')) TABLESPACE TBS_SIDEDB_DA_01);
CREATE UNIQUE INDEX SIDE.IX_PK_RMESG on SIDE.RMESG (AID, MESG_S_UMIDH, MESG_S_UMIDL, MESG_CREA_DATE_TIME) LOCAL;
ALTER TABLE SIDE.RMESG ADD CONSTRAINT IX_PK_RMESG PRIMARY KEY (AID, MESG_S_UMIDH, MESG_S_UMIDL, MESG_CREA_DATE_TIME) USING INDEX SIDE.IX_PK_RMESG;
CREATE INDEX SIDE.ix_rmesg_cassender ON SIDE.rmesg (MESG_CAS_SENDER_REFERENCE) LOCAL;
CREATE INDEX SIDE.ix_rmesg_creationdate ON SIDE.rmesg (MESG_CREA_DATE_TIME) LOCAL;
CREATE INDEX SIDE.ix_rmesg_trnref ON SIDE.rmesg (MESG_TRN_REF) LOCAL;
CREATE INDEX SIDE.ix_rmesg_uumid ON SIDE.rmesg (MESG_UUMID, MESG_UUMID_SUFFIX) LOCAL;
CREATE INDEX SIDE.IX_UNIT_NAME_RMESG on RMESG(mesg_crea_date_time,X_INST0_UNIT_NAME) LOCAL;
CREATE INDEX SIDE.IX_RMESG on RMESG(mesg_crea_date_time ,mesg_type,x_fin_ccy) LOCAL;
CREATE INDEX SIDE.IX_NAME_FORMAT_TYPE_RMESG on RMESG(mesg_frmt_name,mesg_sub_format,mesg_type,mesg_crea_date_time ) LOCAL;same Explain Plan Same Result .
I always remember TOM Quote "full scans are not evil, indexes are not good"
Which Mean Something Wrong Goes with Indexes , the partition depend on MESG_CREA_DATE_TIME Column I create Index for this column but same explain plan Appear every time. With Same Time.
Thank you
Osama -
Explain plan - *,1 col, severals, HUH
I was wondering if someone could explain this to me. I have a simple query that joins three tables and my joins
are on the indexed columns. The stats on each of the tables are not up to date but thay are very close. (eg: stats say 950 records when there are actually 1000).
Anyway, in my query I do a select * and noticed that in the explain plan it was doing full table scans on all of the tables. So then on a whim I just selected the first column from the first table only and all of sudden the explain plan came with two of three indexes. Then when I entered in the names of all the fields of the first table the explain plan changed once again. Only this time it only used one index.
Why would what I select have any bearing on the choices
made in the explain plan. This to me makes absolutely no sense. Does it have something to do with chained or migrated records?The query is
SELECT *
FROM Families t1,
family_memberships t2,
consent_release_form t3
where t1.family_number = t2.family_number
and t2.per_id = t3.per_id
and t3.code < >'03'
In families the PK is family number
In family_membership there is a FK back to families on
family_number. Its PK is fmd_id
In consent_release_forms there is a Index on Per_id and
a PK on consent_id.
There's an intermediate table called PERSONS that slots
between family membership and the consent_release_form table that has a PK of per_id. It wasn't necessary for the query and when i added it to the query with the appropriate links it still made no difference.
WHen I just selected family number in my Select it used all the appropriate indexes because of course family number is the PK of the driving table. But still, even I selected everything why would it use a full table scan on ALL the tables. It wasn't faster. if I added a /*+ RULE */ to the query it used the correct indexes and ran twice as fast.
I just find it odd that this has been happening lately. I never used to run into situations where FTS's were used on all the tables of a query. Maybe one or two of the tables but not all.
Maybe you are looking for
-
The DVD I burned won't play on my DVD player
I filmed my son playing a concert on my iPhone. It is about an hour long. I was able to make it into a quick time movie. I figured out how to bun it on to a DVD throught Finder, but the DVD won't play on my DVD player or the Mac DVD player. What
-
Problem transferring email addresses to IPhone 4
IPhone 4 new user - can not get Yahoo & Google email addresses transferred to IPhone from Macbook
-
Hi, It seems to have little bug in "InsertVersionInfo.sql" -script? Why it tries to write some version info to table (dbo.SchemaChanges) what doesnt exist at all "ManagementServer" db ? (Fresh new installation)
-
My ipod nano 7th generation won't sync ratings to itunes. What can I do?
Hi, I have an Ipod nano 7th generation bought about a month ago and usually has no problems. I've been having an issue with it where it won't sync songs' ratings from the Nano to Itunes. My Ipod is set to manually manage Music and Video. And no ratin
-
Language on BB bold 9700 only english, nor more german
After updating sw to v5.0.0.656 (Platform 5.1.0.153) Cryp Kernel 3.8.5.85 the language is only english (i cannot choose german, no more available) How get i german back? Thamks frank