Why is this query not using the index?
check out this query:-
SELECT CUST_PO_NUMBER, HEADER_ID, ORDER_TYPE, PO_DATE
FROM TABLE1
WHERE STATUS = 'N'
and here's the explain plan:-
1
2 -------------------------------------------------------------------------------------
3 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
4 -------------------------------------------------------------------------------------
5 | 0 | SELECT STATEMENT | | 2735K| 140M| 81036 (2)|
6 |* 1 | TABLE ACCESS FULL| TABLE1 | 2735K| 140M| 81036 (2)|
7 -------------------------------------------------------------------------------------
8
9 Predicate Information (identified by operation id):
10 ---------------------------------------------------
11
12 1 - filter("STATUS"='N')
There is already an index on this column, as is shown below:-
INDEX_NAME INDEX_TYPE UNIQUENESS TABLE_NAME COLUMN_NAME COLUMN_POSITION
1 TABLE1_IDX2 NORMAL NONUNIQUE TABLE1 STATUS 1
2 TABLE1_IDX NORMAL NONUNIQUE TABLE1 HEADER_ID 1
So why is this query not using the index on the 'STATUS' Column?
I've already tried using optimizer hints and regathering the stats on the table, but the execution plan still remains the same, i.e. it still uses a FTS.
I have tried this command also:-
exec dbms_stats.gather_table_stats('GECS','GEPS_CS_SALES_ORDER_HEADER',method_opt=>'for all indexed columns size auto',cascade=>true,degree=>4);
inspite of this, the query is still using a full table scan.
The table has around 55 Lakh records, across 60 columns. And because of the FTS, the query is taking a long time to execute. How do i make it use the index?
Please help.
Edited by: user10047779 on Mar 16, 2010 6:55 AM
If the cardinality is really as skewed as that, you may want to look at putting a histogram on the column (sounds like it would be in order, and that you don't have one).
create table skewed_a_lot
as
select
case when mod(level, 1000) = 0 then 'N' else 'Y' end as Flag,
level as col1
from dual connect by level <= 1000000;
create index skewed_a_lot_i01 on skewed_a_lot (flag);
exec dbms_stats.gather_table_stats(user, 'SKEWED_A_LOT', cascade => true, method_opt => 'for all indexed columns size auto');Is an example.
Similar Messages
-
Why is this query not using my index ?
hey
i have the following situation
(i'm sorry but i can't add the acctual script or output)
create table x as
select level high_card ,
mod(level,1000) medium_card ,
mod(level,10) low_card ,
'***' padding
from dual
connect by level < 100001;
create index x_med_low_ix on x(low_card,medium_card);
create index x_high_ix on x(high_card);
exec dbms_stats.gather_table_stats(user,'x',cascade=>true,method_opt=>'for all indexed columns size auto');
i'm running the following query
select *
from x
where low_card = 70
and medium_card = 70
and high_card = 70;
i'm expecting a range scan on the x_high_ix index. the optimizer expects only one row. the stats on the high_card columns shows that (num_rows * density = 1).
when i run the query the optimizer uses the x_med_low_ix and does 14 cr.
when i force the use of x_high_ix the cr goes down to 4.
i don't want to declare x_high_ix as unique.
so, why isn't he using my index ?It's using that index for me:
SQL> create table x as
2 select level high_card ,
3 mod(level,1000) medium_card ,
4 mod(level,10) low_card ,
5 '***' padding
6 from dual
7 connect by level < 100001;
Table created.
SQL>
SQL> create index x_med_low_ix on x(low_card,medium_card);
Index created.
SQL>
SQL> create index x_high_ix on x(high_card);
Index created.
SQL>
SQL> exec dbms_stats.gather_table_stats(user,'x',cascade=>true,method_opt=>'for all indexed columns
size auto');
PL/SQL procedure successfully completed.
SQL> ed
Wrote file afiedt.buf
1 select *
2 from x
3 where low_card = 70
4 and medium_card = 70
5* and high_card = 70
SQL>
SQL> /
no rows selected
Execution Plan
Plan hash value: 775193209
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 15 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS BY INDEX ROWID| X | 1 | 15 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | X_HIGH_IX | 1 | | 1 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("LOW_CARD"=70 AND "MEDIUM_CARD"=70)
2 - access("HIGH_CARD"=70)
Statistics
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
454 bytes sent via SQL*Net to client
370 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> set autot off
SQL> select * from v$version;
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Productionwhat is your version?
By the way, when i force optimizer to use index X_MED_LOW_IX, it does 2 CR for me. -
Query
SELECT case.case_objid FROM [email protected] case, table_x_cwp_tickect_details_vw t WHERE CASE.case_condition_cd IN ('OPEN', 'OPEN-DISPATCH', 'OPEN-REJECT', 'OPEN-RETURNED') AND case.case_type_cd in ('CUSTOMER FAULT', 'CHRONIC','SCHEDULED ACTIVITY','PROBLEM') AND ROWNUM <= 500 AND case.case_objid = t.ticket_objid AND ( ( case.account_id = '672286' ) ) ORDER BY case.case_id DESC
From PROD
Plan
SELECT STATEMENT HINT: FIRST_ROWS Cost: 2,629 Bytes: 221,500 Cardinality: 500
37 SORT ORDER BY Cost: 2,629 Bytes: 221,500 Cardinality: 500
36 COUNT STOPKEY
35 NESTED LOOPS OUTER Cost: 2,628 Bytes: 279,533 Cardinality: 631
33 HASH JOIN OUTER Cost: 2,627 Bytes: 275,116 Cardinality: 631
31 NESTED LOOPS OUTER Cost: 2,249 Bytes: 266,282 Cardinality: 631
28 NESTED LOOPS Cost: 1,766 Bytes: 257,448 Cardinality: 631
26 NESTED LOOPS Cost: 1,765 Bytes: 253,031 Cardinality: 631
24 NESTED LOOPS Cost: 1,764 Bytes: 248,614 Cardinality: 631
22 NESTED LOOPS Cost: 1,763 Bytes: 244,197 Cardinality: 631
19 NESTED LOOPS Cost: 1,258 Bytes: 235,363 Cardinality: 631
17 NESTED LOOPS Cost: 1,257 Bytes: 230,946 Cardinality: 631
14 NESTED LOOPS OUTER Cost: 752 Bytes: 217,695 Cardinality: 631
12 HASH JOIN Cost: 751 Bytes: 213,278 Cardinality: 631
1 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,052 Cardinality: 1,436
11 HASH JOIN Cost: 748 Bytes: 208,861 Cardinality: 631
2 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,052 Cardinality: 1,436
10 HASH JOIN Cost: 746 Bytes: 204,444 Cardinality: 631
3 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,052 Cardinality: 1,436
9 HASH JOIN Cost: 743 Bytes: 200,027 Cardinality: 631
4 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,052 Cardinality: 1,436
8 NESTED LOOPS Cost: 741 Bytes: 195,610 Cardinality: 631
5 REMOTE REMOTE CASE Cost: 235 Bytes: 156,488 Cardinality: 631
7 TABLE ACCESS BY INDEX ROWID TABLE SA.TABLE_CASE Cost: 1 Bytes: 62 Cardinality: 1
6 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.TC_C_CASE_OBJINDEX Cost: 1 Cardinality: 1
13 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.UN_PTT2CASE Cost: 1 Bytes: 7 Cardinality: 1
16 TABLE ACCESS BY INDEX ROWID TABLE SA.TABLE_SITE Cost: 1 Bytes: 21 Cardinality: 1
15 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.SITE_OBJINDEX Cost: 1 Cardinality: 1
18 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.BUS_ORG_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
21 TABLE ACCESS BY INDEX ROWID TABLE SA.TABLE_ADDRESS Cost: 1 Bytes: 14 Cardinality: 1
20 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.ADDRESS_OBJINDEX Cost: 1 Cardinality: 1
23 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.COUNTRY_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
25 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.CONTACT_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
27 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.CONDITION_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
30 TABLE ACCESS BY GLOBAL INDEX ROWID TABLE SA.TABLE_SITE_PART Cost: 1 Bytes: 14 Cardinality: 1 Partition #: 34
29 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.SITE_PART_OBJINDEX Cost: 1 Cardinality: 1
bold 32 TABLE ACCESS FULL TABLE SA.TABLE_MOD_LEVEL Cost: 376 Bytes: 1,442,084 Cardinality: 103,006 bold
34 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.PART_NUM_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
From DEV platform
Plan
SELECT STATEMENT HINT: FIRST_ROWS Cost: 591 Bytes: 61,134 Cardinality: 138
37 SORT ORDER BY Cost: 591 Bytes: 61,134 Cardinality: 138
36 COUNT STOPKEY
35 HASH JOIN Cost: 590 Bytes: 61,134 Cardinality: 138
1 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,045 Cardinality: 1,435
34 HASH JOIN Cost: 588 Bytes: 60,168 Cardinality: 138
2 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,045 Cardinality: 1,435
33 HASH JOIN Cost: 585 Bytes: 59,202 Cardinality: 138
3 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,045 Cardinality: 1,435
32 HASH JOIN Cost: 583 Bytes: 58,236 Cardinality: 138
4 INDEX FAST FULL SCAN INDEX (UNIQUE) SA.GBST_ELM_OBJINDEX Cost: 2 Bytes: 10,045 Cardinality: 1,435
31 NESTED LOOPS OUTER Cost: 580 Bytes: 57,270 Cardinality: 138
29 NESTED LOOPS OUTER Cost: 579 Bytes: 56,304 Cardinality: 138
27 NESTED LOOPS OUTER Cost: 469 Bytes: 54,372 Cardinality: 138
24 NESTED LOOPS Cost: 363 Bytes: 52,440 Cardinality: 138
22 NESTED LOOPS Cost: 362 Bytes: 51,474 Cardinality: 138
20 NESTED LOOPS Cost: 361 Bytes: 50,508 Cardinality: 138
18 NESTED LOOPS Cost: 360 Bytes: 49,542 Cardinality: 138
15 NESTED LOOPS Cost: 249 Bytes: 47,610 Cardinality: 138
13 NESTED LOOPS Cost: 248 Bytes: 46,644 Cardinality: 138
10 NESTED LOOPS OUTER Cost: 138 Bytes: 43,746 Cardinality: 138
8 NESTED LOOPS Cost: 137 Bytes: 42,780 Cardinality: 138
5 REMOTE REMOTE CASE Cost: 26 Bytes: 34,224 Cardinality: 138
7 TABLE ACCESS BY INDEX ROWID TABLE SA.TABLE_CASE Cost: 1 Bytes: 62 Cardinality: 1
6 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.TC_C_CASE_OBJINDEX Cost: 1 Cardinality: 1
9 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.UN_PTT2CASE Cost: 1 Bytes: 7 Cardinality: 1
12 TABLE ACCESS BY INDEX ROWID TABLE SA.TABLE_SITE Cost: 1 Bytes: 21 Cardinality: 1
11 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.SITE_OBJINDEX Cost: 1 Cardinality: 1
14 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.BUS_ORG_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
17 TABLE ACCESS BY INDEX ROWID TABLE SA.TABLE_ADDRESS Cost: 1 Bytes: 14 Cardinality: 1
16 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.ADDRESS_OBJINDEX Cost: 1 Cardinality: 1
19 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.COUNTRY_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
21 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.CONTACT_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
23 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.CONDITION_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
26 TABLE ACCESS BY GLOBAL INDEX ROWID TABLE SA.TABLE_SITE_PART Cost: 1 Bytes: 14 Cardinality: 1 Partition #: 34
25 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.SITE_PART_OBJINDEX Cost: 1 Cardinality: 1
bold 28 INDEX RANGE SCAN INDEX SA.IND_PART_INFO2PART_NUM Cost: 1 Bytes: 14 Cardinality: 1 bold
30 INDEX UNIQUE SCAN INDEX (UNIQUE) SA.PART_NUM_OBJINDEX Cost: 1 Bytes: 7 Cardinality: 1
Conclusion:
IND_PART_INFO2PART_NUM is not in use in Production environment
PROD
1. SQL> select index_name,NUM_ROWS,CLUSTERING_FACTOR from dba_indexes where index_name='IND_PART_INFO2PART_NUM';
INDEX_NAME NUM_ROWS CLUSTERING_FACTOR
IND_PART_INFO2PART_NUM 103023 46488
DEV environment
SQL> select index_name,NUM_ROWS,CLUSTERING_FACTOR,table_name from dba_indexes where index_name='IND_PART_INFO2PART_NUM';
INDEX_NAME NUM_ROWS CLUSTERING_FACTOR TABLE_NAME
IND_PART_INFO2PART_NUM 101982 45722 TABLE_MOD_LEVEL
1. Index is rebuild
2. stats are up to date
3. Redef on table is done.
Still no change in the plan .Osama-mustafa wrote:
Aman.... wrote:
Osama-mustafa wrote:
alter index <index-name> rebuild ;Why?
Aman....I faced this issue with query and indexes was need rebuildWhat issue Osama-that query wasn't using index and after rebuild it did start using it? Not just that this reply is wrong , this is OP has mentioned that he has done already. Please note that index rebuild is not the answer when the query is not using the index. There can be many reasons behind it. Have a look at Richard Foote's blog where he explains all of this in a very detailed way and in many posts.
Aman.... -
Why my select is not using the index
This is my index
CREATE INDEX CONFIG_STATE_IDX ON IDENTIFIER
(CONFIGURATION_ID, STATE)
LOGGING
TABLESPACE NII_INDEX
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
FREELISTS 1
FREELIST GROUPS 1
BUFFER_POOL DEFAULT
NOPARALLEL;
This is my select statement:
SELECT *
FROM identifier i
WHERE
i.configuration_id = '89afead40a0c0b8d00628c59aa405ea4'
AND i.state = 'QT'
AND ROWNUM <6
This is my exmplain plan result
Operation Object Name Rows Bytes Cost Object Node In/Out PStart PStop
SELECT STATEMENT Hint=CHOOSE 5 2128
COUNT STOPKEY
TABLE ACCESS FULL IDENTIFIER 133 K 19 M 2128
Why it is not using the index on configuration_id and state.Possibility one: you didn't do an analyze statistics on the table and/or the index after index creation.
Possibility two: The optimizer has determined that it can return the query result set with fewer I/Os if it does a FTS vs using the index (the optimizer is very keen on I/Os). -
Why does it not use the index?
L.S.,
We are using a table called IT_RFC_REGISTRATION. It is a relatively big table for our application.
Its primary key is RFCNR, each new RFCNR getting the next value.
Now for my intranet report I am interested in the last 40 records. But when I execute:
SELECT *
FROM IT_RFC_REGISTRATION
ORDER BY RFCNR DESC
the query takes ages to execute.
When I do this:
SELECT RFCNR
FROM IT_RFC_REGISTRATION
ORDER BY RFCNR DESC
the result comes instantaneous because this query uses the index on RFCNR.
Why does the former query not use the index to execute? It should be much faster to fetch ROWIDs from the index end to start and use those to get the records, than to load all the records and then sort them.
Is there a trick with which I can use a join of the latter query and the former query to speed up the result?
Greetings,
Philbert de Zwart,
Utrecht, The Netherlands.The difference you see in query run time is based on the amount data being sorted, then returned. In the first query, a full table scan is faster since if the index was used, Oracle would have to do a lookup in the index, get the rowid's and go look up the data in the table (TWO disk i/o's). It's faster to just scan the entire table.
Indexes will generally not be used unless you have a where clause. If you only need a few fields from the table, you could include them all in an index. For instance, if you only need RFCNR & DESC create a concatenated index on those two columns and then only a scan of the index is required (very fast). -
Can I refactor this query to use an index more efficiently?
I have a members table with fields such as id, last name, first name, address, join date, etc.
I have a unique index defined on (last_name, join_date, id).
This query will use the index for a range scan, no sort required since the index will be in order for that range ('Smith'):
SELECT members.*
FROM members
WHERE last_name = 'Smith'
ORDER BY joindate, idIs there any way I can get something like the following to use the index (with no sort) as well:
SELECT members.*
FROM members
WHERE last_name like 'S%'
ORDER BY joindate, idI understand the difficulty is probably; even if it does a range scan on every last name 'S%' (assuming it can?), they're not necessarily in order. Case in point:
Last_Name: JoinDate:
Smith 2/5/2010
Smuckers 1/10/2010An index range scan of 'S%' would return them in the above order, which is not ordered by joindate.
So is there any way I can refactor this (query or index) such that the index can be range scanned (using LIKE 'x%') and return rows in the correct order without performing a sort? Or is that simply not possible?xaeryan wrote:
I have a members table with fields such as id, last name, first name, address, join date, etc.
I have a unique index defined on (last_name, join_date, id).
This query will use the index for a range scan, no sort required since the index will be in order for that range ('Smith'):
SELECT members.*
FROM members
WHERE last_name = 'Smith'
ORDER BY joindate, idIs there any way I can get something like the following to use the index (with no sort) as well:
SELECT members.*
FROM members
WHERE last_name like 'S%'
ORDER BY joindate, idI understand the difficulty is probably; even if it does a range scan on every last name 'S%' (assuming it can?), they're not necessarily in order. Case in point:
Last_Name: JoinDate:
Smith 2/5/2010
Smuckers 1/10/2010An index range scan of 'S%' would return them in the above order, which is not ordered by joindate.
So is there any way I can refactor this (query or index) such that the index can be range scanned (using LIKE 'x%') and return rows in the correct order without performing a sort? Or is that simply not possible?Come on. Index column order does matter. "LIKE 'x%'" actually is full table scan. The db engine accesses contiguous index entries and then uses the ROWID values in the index to retrieve the table rows. -
Why is Oracle not using the index??
Hi,
I have a table called 'arc_errors' which has an index on 'member_number' as follows:- Create/Recreate indexes
create index DWO.DW_ARC_CERRORS_MNO on DWO.DW_ARC_CERRORS (MEMBER_NUMBER);
But surpisingly, when I execute the following query, it does not use the index.
SELECT member_number,
COUNT(*) error_count
FROM arc_errors a
WHERE member_number = 68534152 AND
( tx_type = 'SDIC' AND
error_number IN (4, 7, 12, 13, 15, 17, 18, 705) )
OR
( tx_type = 'AUTH' AND
error_number IN (100, 104, 107, 111, 116) )
OR
( tx_type = 'BHO' AND
error_number IN (708,710) )
OR
( tx_type = 'XLGN' AND
( error_number BETWEEN 102 AND 105 OR
error_number BETWEEN 107 AND 120 OR
error_number BETWEEN 300 AND 304 ) )
OR
( tx_type = 'None' AND
( error_number IN (20, 112) OR
error_number BETWEEN 402 AND 421 ) )
OR
( tx_type = 'HYBR' AND
error_number IN (303, 304) )
GROUP BY member_number;
This is what 'explain plan' tell me
SELECT STATEMENT, GOAL = RULE 237907 502923 15087690
SORT GROUP BY 237907 502923 15087690
PARTITION RANGE ALL
TABLE ACCESS FULL DWO DW_ARC_CERRORS 237209 502923 15087690
Can someone tell me why a 'table acess full' is required here?
Thanks in advance,
RajeshSorry, I just found the solution myself. I need to put an extra pair of braces around the set of conditions seperated by OR.
-
Why my query not using any index but doing a FULL TABLE SCAN
Hi,
My EXPLAIN PLAN output is
Plan hash value: 1163866984
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 774 | 159K| | 40847 (2)| 00:08:11 |
|* 1 | FILTER | | | | | | |
| 2 | SORT GROUP BY | | 774 | 159K| | 40847 (2)| 00:08:11 |
|* 3 | HASH JOIN | | 77337 | 15M| 9744K| 40843 (2)| 00:08:11 |
|* 4 | HASH JOIN | | 77337 | 8836K| 5896K| 20987 (2)| 00:04:12 |
|* 5 | HASH JOIN | | 77337 | 4984K| | 9292 (3)| 00:01:52 |
|* 6 | HASH JOIN | | 24991 | 951K| | 3349 (3)| 00:00:41 |
|* 7 | TABLE ACCESS FULL| IDS_TXNIDNUMBERS | 24991 | 683K| | 2328 (3)| 00:00:28 |
| 8 | TABLE ACCESS FULL| IDS_TXNDEMDATAMAP | 2419K| 25M| | 1006 (3)| 00:00:13 |
| 9 | TABLE ACCESS FULL | IDS_IDNUMBERS | 7435K| 191M| | 5903 (2)| 00:01:11 |
| 10 | TABLE ACCESS FULL | IDS_DEMDATA | 2583K| 125M| | 3683 (5)| 00:00:45 |
| 11 | TABLE ACCESS FULL | IDS_TXN | 2583K| 231M| | 6403 (1)| 00:01:17 |
----------------------------------------------------------------------------------------------------- All my 5 tables IDS_TXNIDNUMBERS, IDS_TXNDEMDATAMAP, IDS_IDNUMBERS,IDS_DEMDATA, IDS_TXN has indexes in relevant columns. Is it cause less time so CBO is not using the indexes.
Thanks
Amitava.amitavachatterjee1975 wrote:
Please be polite when responding to my queries. If you find these questions not to your standard, stay away from them. This is an open forum and I have got my full rights to ask questions.Unsure, what wrong did you find in SB's reply. I find those links perfectly knowledgeable. The question of having so many unanswered questions probably pricked you a little too much. But that, IMO, is a legitimate question, to be asked to a User who even after being associated with OTN for over an year has 100% record of not getting an answer.
For your original question, you will have to provide more details to allow people to answer you.
You must read {message:id=3292438} and post the mentioned details. People do not carry a Crystal Ball to identify the problem merely by reading few lines of Problem description and Explain plans. Do not make people guess, provide appropriate details, to help them Help "You". -
SQL Query not using Composite Index
Hi,
Please look at the below query:
SELECT pde.participant_uid
,pde.award_code
,pde.award_type
,SUM(decode(pde.distribution_type
,'FORFEITURE'
,pde.forfeited_quantity *
pde.sold_price * cc.rate
,pde.distributed_quantity *
pde.sold_price * cc.rate)) AS gross_Amt_pref_Curr
FROM part_distribution_exec pde
,currency_conversion cc
,currency off_curr
WHERE pde.participant_uid = 4105
AND off_curr.currency_iso_code =
pde.offering_currency_iso_code
AND cc.from_currency_uid = off_curr.currency_uid
AND cc.to_currency_uid = 1
AND cc.latest_flag = 'Y'
GROUP BY pde.participant_uid
,pde.award_code
,pde.award_type
In oracle 9i, i"ve executed this above query, it takes 6 seconds and the cost is 616, this is due to non usage of the composite index, Currency_conversion_idx(From_currency_uid, To_currency_uid, Latest_flag). I wonder why this index is not used while executing the above query. So, I've dropped the index and recreated it. Now, the query is using this index. After inserting many rows or say in 1 days time, if the same query is executed, again the query is not using the index. So everyday, the index should be dropped and recreated.
I don't want this drop and recreation of index daily, I need a permanent solution for this.
Can anyone tell me, Why this index goes stale after a period of time???? Please take some time and Solve this issue.
-SankarHi David,
This is Sankar here. Thankyou for your reply.
I've got the plan table output for this problematic query, please go thro' it and help me out why the index CURRENCY_CONVERSION_IDX is used now and why it's not using while executing the query after a day or inserting some records...
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost |
| 0 | SELECT STATEMENT | | 26 | 15678 | 147 |
| 1 | TABLE ACCESS BY INDEX ROWID | PART_AWARD_PAYOUT_SCHEDULE | 1 | 89 | 2 |
|* 2 | INDEX UNIQUE SCAN | PART_AWARD_PAYOUT_SCHEDULE_PK1 | 61097 | | 1 |
| 3 | SORT AGGREGATE | | 1 | 67 | |
|* 4 | FILTER | | | | |
|* 5 | INDEX RANGE SCAN | PART_AWARD_PAYOUT_SCHEDULE_PK1 | 1 | 67 | 2 |
| 6 | SORT AGGREGATE | | 1 | 94 | |
|* 7 | FILTER | | | | |
|* 8 | TABLE ACCESS BY INDEX ROWID | PART_AWARD_PAYOUT_SCHEDULE | 1 | 94 | 3 |
|* 9 | INDEX RANGE SCAN | PART_AWARD_PAYOUT_SCHEDULE_PK1 | 1 | | 2 |
|* 10 | FILTER | | | | |
|* 11 | HASH JOIN | | 26 | 15678 | 95 |
|* 12 | HASH JOIN OUTER | | 26 | 11596 | 91 |
|* 13 | HASH JOIN | | 26 | 10218 | 86 |
| 14 | VIEW | | 1 | 82 | 4 |
| 15 | SORT GROUP BY | | 1 | 116 | 4 |
|* 16 | TABLE ACCESS BY INDEX ROWID | PART_AWARD_LEDGER | 1 | 116 | 2 |
|* 17 | INDEX RANGE SCAN | PARTICIPANT_UID_IDX | 1 | | 1 |
|* 18 | HASH JOIN OUTER | | 26 | 8086 | 82 |
|* 19 | HASH JOIN | | 26 | 6006 | 71 |
| 20 | NESTED LOOPS | | 36 | 5904 | 66 |
| 21 | NESTED LOOPS | | 1 | 115 | 65 |
| 22 | TABLE ACCESS BY INDEX ROWID | CURRENCY_CONVERSION | 18 | 756 | 2 |
|* 23 | INDEX RANGE SCAN | KLS_IDX_CURRENCY_CONV | 3 | | 1 |
| 24 | VIEW | | 1 | 73 | 4 |
| 25 | SORT GROUP BY | | 1 | 71 | 4 |
| 26 | TABLE ACCESS BY INDEX ROWID| PART_AWARD_VALUE | 1 | 71 | 2 |
|* 27 | INDEX RANGE SCAN | PAV_PARTICIPANT_UID_IDX | 1 | | 1 |
| 28 | TABLE ACCESS BY INDEX ROWID | PARTICIPANT_AWARD | 199 | 9751 | 1 |
|* 29 | INDEX UNIQUE SCAN | PARTICIPANT_AWARD_PK1 | 100 | | |
|* 30 | INDEX FAST FULL SCAN | PARTICIPANT_AWARD_TYPE_PK1 | 147 | 9849 | 4 |
| 31 | VIEW | | 1 | 80 | 10 |
| 32 | SORT GROUP BY | | 1 | 198 | 10 |
|* 33 | TABLE ACCESS BY INDEX ROWID | CURRENCY_CONVERSION | 1 | 42 | 2 |
| 34 | NESTED LOOPS | | 1 | 198 | 8 |
| 35 | NESTED LOOPS | | 2 | 312 | 4 |
| 36 | TABLE ACCESS BY INDEX ROWID| PART_DISTRIBUTION_EXEC | 2 | 276 | 2 |
|* 37 | INDEX RANGE SCAN | IND_PARTICIPANT_UID | 1 | | 1 |
| 38 | TABLE ACCESS BY INDEX ROWID| CURRENCY | 1 | 18 | 1 |
|* 39 | INDEX UNIQUE SCAN | CURRENCY_AK | 1 | | |
|* 40 | INDEX RANGE SCAN | CURRENCY_CONVERSION_AK | 2 | | 1 |
| 41 | VIEW | | 1 | 53 | 4 |
| 42 | SORT GROUP BY | | 1 | 62 | 4 |
|* 43 | TABLE ACCESS BY INDEX ROWID | PART_AWARD_VESTING | 1 | 62 | 2 |
|* 44 | INDEX RANGE SCAN | PAVES_PARTICIPANT_UID_IDX | 1 | | 1 |
| 45 | TABLE ACCESS FULL | AWARD | 1062 | 162K| 3 |
| 46 | TABLE ACCESS BY INDEX ROWID | CURRENCY | 1 | 18 | 2 |
|* 47 | INDEX UNIQUE SCAN | CURRENCY_AK | 102 | | 1 |
Predicate Information (identified by operation id):
2 - access("PAPS"."AWARD_CODE"=:B1 AND "PAPS"."PARTICIPANT_UID"=4105 AND "PAPS"."AWARD_TYPE"=:B2
"PAPS"."INSTALLMENT_NUM"=1)
4 - filter(4105=:B1)
5 - access("PAPS"."AWARD_CODE"=:B1 AND "PAPS"."PARTICIPANT_UID"=4105 AND "PAPS"."AWARD_TYPE"=:B2)
7 - filter(4105=:B1)
8 - filter("PAPS"."STATUS"='OPEN')
9 - access("PAPS"."AWARD_CODE"=:B1 AND "PAPS"."PARTICIPANT_UID"=4105 AND "PAPS"."AWARD_TYPE"=:B2)
10 - filter("CC_A_P_CURR"."FROM_CURRENCY_UID"= (SELECT /*+ */ "CURRENCY"."CURRENCY_UID" FROM
"EWAPDBO"."CURRENCY" "CURRENCY" WHERE "CURRENCY"."CURRENCY_ISO_CODE"=:B1))
11 - access("SYS_ALIAS_7"."AWARD_CODE"="A"."AWARD_CODE")
12 - access("SYS_ALIAS_7"."AWARD_CODE"="PVS"."AWARD_CODE"(+))
13 - access("SYS_ALIAS_8"."AWARD_CODE"="PALS"."AWARD_CODE" AND
"SYS_ALIAS_8"."AWARD_TYPE"="PALS"."AWARD_TYPE")
16 - filter(TRUNC("PAL1"."LEDGER_ENTRY_DATE")<=TRUNC(SYSDATE@!) AND "PAL1"."ALLOC_TYPE"='IPU')
17 - access("PAL1"."PARTICIPANT_UID"=4105)
filter("PAL1"."PARTICIPANT_UID"=4105)
18 - access("SYS_ALIAS_8"."AWARD_CODE"="PDES"."AWARD_CODE"(+) AND
"SYS_ALIAS_8"."AWARD_TYPE"="PDES"."AWARD_TYPE"(+))
19 - access("SYS_ALIAS_7"."AWARD_CODE"="SYS_ALIAS_8"."AWARD_CODE")
23 - access("CC_A_P_CURR"."TO_CURRENCY_UID"=1 AND "CC_A_P_CURR"."LATEST_FLAG"='Y')
27 - access("PAV"."PARTICIPANT_UID"=4105)
filter("PAV"."PARTICIPANT_UID"=4105)
29 - access("SYS_ALIAS_7"."AWARD_CODE"="SYS_ALIAS_9"."AWARD_CODE" AND
"SYS_ALIAS_7"."PARTICIPANT_UID"=4105)
30 - filter("SYS_ALIAS_8"."PARTICIPANT_UID"=4105)
33 - filter("CC"."LATEST_FLAG"='Y')
37 - access("PDE"."PARTICIPANT_UID"=4105)
filter("PDE"."PARTICIPANT_UID"=4105)
39 - access("OFF_CURR"."CURRENCY_ISO_CODE"="PDE"."OFFERING_CURRENCY_ISO_CODE")
40 - access("CC"."FROM_CURRENCY_UID"="OFF_CURR"."CURRENCY_UID" AND "CC"."TO_CURRENCY_UID"=1)
43 - filter("PV"."VESTING_DATE"<=SYSDATE@!)
44 - access("PV"."PARTICIPANT_UID"=4105)
filter("PV"."PARTICIPANT_UID"=4105)
47 - access("CURRENCY"."CURRENCY_ISO_CODE"=:B1)
Note: cpu costing is off
93 rows selected.
Please help me out...
-Sankar -
How can i know if my query is using the index ?
Hello...
How can i know if my query is using the index of the table or not?
im using set autotrace on...but is there another way to do it?
thanks!
Alessandro Falanque.Hi,
You can use Explain Plan for checking that your query is using proper index or not. First you need to check that Plan_table is installed in your database or not. If it is not there THEN THE SCRIPT WILL BE LIKE THIS:
CREATE TABLE PLAN_TABLE (
STATEMENT_ID VARCHAR2 (30),
TIMESTAMP DATE,
REMARKS VARCHAR2 (80),
OPERATION VARCHAR2 (30),
OPTIONS VARCHAR2 (30),
OBJECT_NODE VARCHAR2 (128),
OBJECT_OWNER VARCHAR2 (30),
OBJECT_NAME VARCHAR2 (30),
OBJECT_INSTANCE NUMBER,
OBJECT_TYPE VARCHAR2 (30),
OPTIMIZER VARCHAR2 (255),
SEARCH_COLUMNS NUMBER,
ID NUMBER,
PARENT_ID NUMBER,
POSITION NUMBER,
COST NUMBER,
CARDINALITY NUMBER,
BYTES NUMBER,
OTHER_TAG VARCHAR2 (255),
PARTITION_START VARCHAR2 (255),
PARTITION_STOP VARCHAR2 (255),
PARTITION_ID NUMBER,
OTHER LONG,
DISTRIBUTION VARCHAR2 (30))
TABLESPACE SYSTEM NOLOGGING
PCTFREE 10
PCTUSED 40
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 10240
NEXT 10240
PCTINCREASE 50
MINEXTENTS 1
MAXEXTENTS 121
FREELISTS 1 FREELIST GROUPS 1 )
NOCACHE;
After that write the following command in the SQL prompt.
Explain plan for (Select statement);
Select level, SubStr( lpad(' ',2*(Level-1)) || operation || ' ' ||
object_name || ' ' || options || ' ' ||
decode(id, null , ' ', decode(position, null,' ', 'Cost = ' || position) ),1,100)
|| ' ' || nvl(other_tag, ' ') Operation
from PLAN_TABLE
start with id = 0
connect by
prior id = parent_id;
This will show how the query is getting executed . What are all the indexes it is using etc.
Cheers.
Samujjwal Basu -
Why is my SQL not using an index?
I have a small SQL query (10g) where I join to basic table together on a customer_id column.
select *
from customer c
inner join work_item sp1 ON sp1.customer_id = c.customer_id
and I am using TOAD, which tells me (in the Explain Plan area), that I'm doing a "TABLE ACCESS FULL" scan on the customer table.
But when I look at the details of BOTH tables, I can clearly see that they both have an index on the customer field, and they are both the same data types...
The interesting thing, is that if I change the query to only select data from the work_item table,
select sp1.*
from customer c
inner join work_item sp1 ON sp1.customer_id = c.customer_id
I can see that the indexes are being used...
Why is this? I must be able to select certain columns from the customer table, but why would it not use an index when I do?
Thanks!If I understand correctly, below is a simple test case.
I created a small table and indexed "object_id" column.
When I issue "Select * from t" optimizer goes with FULL TABLE SCAN, whereas wehn "select OBJECT_ID from t" is issued, optimizer chooses to read from the index instead of accessing the table. This is because FAST FULL SCAN is far cheaper than a FTS in this case.
SQL> create table t as select object_id, object_name from all_objects;
Table created.
SQL> exec dbms_stats.gather_table_stats(user, 't');
PL/SQL procedure successfully completed.
SQL> create index t_idx1 on t(object_id);
Index created.
SQL> set autotrace traceonly exp
SQL> select * from t;
Execution Plan
Plan hash value: 1601196873
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 37932 | 1074K| 55 (2)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T | 37932 | 1074K| 55 (2)| 00:00:01 |
SQL> select object_id from t;
Execution Plan
Plan hash value: 3958994525
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 37932 | 185K| 25 (0)| 00:00:01 |
| 1 | INDEX FAST FULL SCAN| T_IDX1 | 37932 | 185K| 25 (0)| 00:00:01 |
SQL> -
Spatial Query not using Spatial Index
Hi All,
I have a query which uses the SDO_WITHIN_DISTANCE operator, but is taking far too long to complete.
SELECT
RT.*,RD.RPD_NODE_ID, RD.RPD_XCOORD,RD.RPD_YCOORD
FROM
railplan_data RD
LEFT JOIN Walk_data_sets WDS ON RD.RPD_RPS_ID = WDS.WDS_RPS_ID
LEFT JOIN RWNet_Temp RT ON WDS.WDS_ID = RT.RW_WDS_ID
WHERE
WDS.wds_id = 441
AND
MDSYS.SDO_WITHIN_DISTANCE(RT.RW_GEOM,RD.RPD_GEOLOC,'DISTANCE=' || TO_CHAR(RT.RW_BUFFER) || ' UNIT=METER') = 'TRUE';
Upon generation of the explain plan I have realised that the spatial index is not being used in the query, but I can't for the life of me get the thing working
3 | Id | Operation | Name | Rows | Bytes |TempSpc| Cost |
4 ------------------------------------------------------------------------------------------
5 | 0 | SELECT STATEMENT | | 25841 | 99M| | 201 |
6 |* 1 | FILTER | | | | | |
7 | 2 | MERGE JOIN OUTER | | | | | |
8 |* 3 | HASH JOIN | | 12652 | 420K| 2968K| 185 |
9 | 4 | TABLE ACCESS FULL | RAILPLAN_DATA | 75910 | 2075K| | 60 |
10 | 5 | TABLE ACCESS BY INDEX ROWID| WALK_DATA_SETS | 1 | 6 | | 1 |
11 |* 6 | INDEX UNIQUE SCAN | WDS_PK | 1 | | | |
12 |* 7 | SORT JOIN | | 16 | 63760 | | 16 |
13 |* 8 | TABLE ACCESS FULL | RWNET_TEMP | 16 | 63760 | | 4 |
If anyone could help me out in figuring out why the spatial index is not being used, I would be most appreciative.
TIA
DanHi all again,
Well I finally got an upgrade to Oracle 10 (yay!), so I am now trying to implement the SDO_JOIN method as per my earlier posts. In fact it is actually working, but I have a question. When I run an explain plan it does not show the use of any domain indexes which I would expect to see, but performs fine (1.07s) with just a few records (10 in 1 table, 15000 in the other), please see code and explain plan below:
SELECT
Distinct
RT.RW_ID, RD.RPD_NODE_ID,
RD.RPD_XCOORD,RD.RPD_YCOORD
FROM
RPD_TEMP_762 RD,
WALK_DATA_SETS WDS,
RWNET_TEMP RT,
TABLE
(SDO_JOIN
( 'RWNET_TEMP',
'RW_GEOM',
'RPD_TEMP_762',
'RPD_GEOLOC',
'distance= ' || TO_CHAR(RT.RW_BUFFER) || ' unit=meter')) SPATIAL_JOIN_RESULT
WHERE WDS.WDS_ID = RT.RW_WDS_ID
AND WDS.WDS_ID = 762
AND SPATIAL_JOIN_RESULT.ROWID1 = RT.ROWID
AND SPATIAL_JOIN_RESULT.ROWID2 = RD.ROWID
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
| 0 | SELECT STATEMENT | | 74 | 5994 | 21753 (1)|
| 1 | SORT UNIQUE | | 74 | 5994 | 21691 (1)|
|* 2 | HASH JOIN | | 1046K| 80M| 1859 (1)|
| 3 | NESTED LOOPS | | 6076 | 213K| 1824 (1)|
| 4 | NESTED LOOPS | | 74 | 2516 | 194 (1)|
|* 5 | INDEX UNIQUE SCAN | WDS_PK | 1 | 4 | 0 (0)|
|* 6 | TABLE ACCESS FULL | RWNET_TEMP | 74 | 2220 | 194 (1)|
|* 7 | COLLECTION ITERATOR PICKLER FETCH| SDO_JOIN | | | |
| 8 | TABLE ACCESS FULL | RPD_TEMP_762 | 17221 | 756K| 28 (0)|
------------------------------------------------------------------------------------------ When i try to add hints to force the use of spatial indexes the performance of this query drops through the floor (it takes minutes / hours), index hint shown below:
/*+ ORDERED INDEX(RW rw_geom) INDEX(RD rpd_geoloc) */My question is is the first query using domain indexes, and if not, how do I get it to?
TIA
Dan -
Hi,
I have a Z-Table. The Primary key is:
EQUNR and LFDNR
I created now a new index with the field: EQUNR BSTNK .
Now I entered 3 equnrs and bstnk like 07* in SE16n
Normally what I thought should happen is that it uses the index to read the three equipments and than checks the field bstnk.
Instead it does a sequentiel read of the hole table that contains 12mio entries!
When I enter the bstnk more qualified like 0712354* the search is fast (1sec). Why is SAP bypassing the index and does a sequentiel read instead?!Hi I checked,
ST05 the fast run was using an Index, the second didn't!
Thanks to John. After I started a runstat on this table it worked.
But the weird thing is when I use a inner join between my Z-Table and the EQUI table it doesn't use the index.
When I first select all equnrs in EQUI and then select the data from my z-Table with for all entries it uses my new index!
Example:
EQUNR has Index on field SERNR
Z-Table has Index on EQUNR + BSTNK
in sernrs I have ~5 full qualified sernos
in bstnk I have something like 07*
3 of these serialnumbers are in a bstnk that begins with 07.
select *
into corresponding fields of table search_result
from equi as a
inner join z-table as b on b~equnr = a~equnr
where a~sernr in sernrs
and b~bstnk in bstnks
After 5 min I have to kill the process. in SM50 I can see sequential read...
When I do this:
select equnr
from equi
into corresponding fields of table lt_search_result
where sernr in sernrs.
select *
from z_table
into corresponding fields of table lt_search_result
for all entries in lt_search_result
where equnr = lt_search_result-equnr
and bstnk in bstnks.
It takes 2sec and I got the result.
Edited by: Daniel Winter on Apr 21, 2010 8:51 AM
Edited by: Daniel Winter on Apr 21, 2010 8:51 AM -
Query on virtual column that is defined in XMLIndex does not use the index
Hello,
I am facing an issue in executing queries on a virtual column that is defined in an XMLIndex: it appears as if the index is not used.
Database details:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
For this use case the XML documents adhere to the following XSD and are stored in an XMLType column in a table:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://a_name_space/v1"
targetNamespace="http://a_name_space/v1"
elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
<xsd:element name="fields">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="field" maxOccurs="unbounded">
<xsd:complexType>
<xsd:choice>
<xsd:element name="value" minOccurs="1" maxOccurs="1">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="notEmptyString4000Type"/>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="values" minOccurs="1" maxOccurs="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" minOccurs="1" maxOccurs="1">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="notEmptyString4000Type">
<xsd:attribute name="startDate" type="xsd:date" use="required"/>
<xsd:attribute name="endDate" type="xsd:date" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:attribute name="name" type="string30Type" use="required"/>
<xsd:attribute name="type" type="dataType" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="dataType">
<xsd:annotation>
<xsd:documentation>Char, Date, Number</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="C"/>
<xsd:enumeration value="D"/>
<xsd:enumeration value="N"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="string30Type">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="30"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="notEmptyString4000Type">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="4000"/>
<xsd:pattern value=".+"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>A field can have a single value as well as multiple values.
The XMLIndex is defined as follows:
CREATE INDEX test_xmltype_idx ON test_xmltype (additional_fields) INDEXTYPE IS XDB.XMLIndex
PARAMETERS
XMLTable dt_fld_tab (TABLESPACE "TAB_SPACE" COMPRESS FOR OLTP) ''fields/field''
COLUMNS
name varchar2(30 char) PATH ''@name''
,dataType varchar2(1 char) PATH ''@type''
,val varchar2(4000 char) PATH ''value/text()''
,vals XMLType PATH ''values/value'' VIRTUAL
XMLTable dt_fld_multi_value_tab (TABLESPACE "TAB_SPACE" COMPRESS FOR OLTP) ''value'' passing vals
COLUMNS
val varchar2(4000) PATH ''text()''
,startDate varchar2(30 char) PATH ''@startDate''
,endDate varchar2(30 char) PATH ''@endDate''
');The following b-tree indexes are defined:
create index dt_field_name_idx on dt_fld_tab (name);
create index dt_field_value_idx on dt_fld_tab (val);
create index dt_field_values_idx on dt_fld_multi_value_tab (val);And stats are properly computed before the queries are executed:
call dbms_stats.gather_table_stats(user, 'test_xmltype', estimate_percent => null);Queries for single values are cost efficient and fast. With 600K rows in the table these return with 0.002 seconds.
Queries for multi-valued fields / elements are not though, these result in a full table scan.
Sample XML snippet:
<fields>
<field name="multiVal" type="C">
<values>
<value startDate="2013-01-01" endDate="2013-01-01">100</value>
<value startDate="2014-01-01">120</value>
</values>
</field>
</fields>Examples of costly and slow queries:
select id from test_xmltype
where xmlexists('/fields/field/@name="multiVal"' passing additional_fields)
and xmlexists('/fields/field/values/value[@startDate="2013-01-01"]' passing additional_fields)
and xmlexists('/fields/field/values/value[text()="100"]' passing additional_fields)
select id from test_xmltype
where xmlexists('/fields/field/@name="multiVal"' passing additional_fields)
and xmlexists('/fields/field/values/value[@startDate="2013-01-01" and .="100"]' passing additional_fields);Whereas the following query on the multi valued field is fast:
select id from test_xmltype
where xmlexists('/fields/field/@name="multiVal"' passing additional_fields)
and xmlexists('/fields/field/values/value[@startDate="2013-01-01"]' passing additional_fields);For the XPath /fields/field/values/value[@startDate="2013-01-01"] the index is used.
Suspected cause: XPath issue for the value of a multi valued field, e.g. /fields/field/values/value[text()="aValue"].
Any hints are appreciated: what am I overlooking here?
Thanks in advance,
-Sjoerd
Edited by: user615230 on May 27, 2013 7:46 AMHello,
This is using binary XML. The table creation script is:
create table test_xmltype
(id number(14,0) not null primary key
,member_code varchar2(30 char) not null
,period_code varchar2(30 char) not null
,amount number(12,2) not null
,additional_fields xmltype
);The schema is not registered in the database. Is that required? It is primarily used to generate Java classes that will be used in order to construct the XML documents.
And you are right: for our initial investigation the sample XML documents are generated with a PLSQL routine and do not contain namespaces. But for the single valued fields there are also no namespaces and the queries on these are executed with very satisfactory plans.
Thanks for the swift reply.
-Sjoerd -
I have issue with a query as follows. It is not using index when i keep a function on the left hand side of comparison in where condition.
But when I remove the function it is using index.
With BLC AS
Name Null? Type
ID NOT NULL NUMBER
MASTER_VALUE NOT NULL NUMBER(8)
DESC_TEXT_ID NUMBER
GVM VARCHAR2(50)
MASTER_LOOKUP_ID NOT NULL NUMBER
WORK_SECTION_ID NUMBER
AUDIT_TRAIL_NO NUMBER
SQL> SELECT COUNT(*) FROM BLC;
COUNT(*)
7769
SQL> SELECT COUNT(DISTINCT(GVM)) "distinct" FROM BLC;
distinct
1350
SQL> SELECT COUNT(*) "nulls" FROM BLC WHERE GVM IS NULL;
nulls
6419
SQL> SELECT COLUMN_NAME,INDEX_NAME FROM DBA_IND_COLUMNS WHERE TABLE_NAME='BLC';
COLUMN_NAME INDEX_NAME
MASTER_LOOKUP_ID LKPCDE_MSTLKP_FK_I
WORK_SECTION_ID LKPCDE_WRKSEC_FK_I
GVM LKPCDE_UK
MASTER_VALUE LKPCDE_MASTERID_VALUE_UK
MASTER_LOOKUP_ID LKPCDE_MASTERID_VALUE_UK
ID LKPCDE_PK
SQL> EXPLAIN PLAN FOR SELECT ID FROM BLC WHERE UPPER ( GVM) = 'MAIN_ORG';
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
Plan hash value: 3196655606
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time|
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 78 | 624 | 18 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| BLC | 78 | 624 | 18 (0)| 00:00:01 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter(UPPER("GVM")='MAIN_ORG')
13 rows selected.
SQL> EXPLAIN PLAN FOR SELECT ID FROM BLC WHERE GVM
= 'MAIN_ORG';
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
Plan hash value: 1620245961
| Id | Operation | Name | Rows | Bytes | Cost (%
CPU)| Time |
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 1 | 8 | 2
(0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| BLC | 1 | 8 | 2
(0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | LKPCDE_UK | 1 | | 1
(0)| 00:00:01 |
PLAN_TABLE_OUTPUT
Predicate Information (identified by operation id):
2 - access("GVM"='MAIN_ORG')
14 rows selected.
SQL> EXPLAIN PLAN FOR SELECT /* INDEX(LKPCDE_UK) */ ID FROM BLC WHE
RE UPPER ( GVM ) = 'MAIN_ORG';
Explained.
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
Plan hash value: 3196655606
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 78 | 624 | 18 (0)| 00:0
0:01 |
|* 1 | TABLE ACCESS FULL| BLC | 78 | 624 | 18 (0)| 00:0
0:01 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter(UPPER("GVM")='MAIN_ORG')
13 rows selected.
Please let me know how i can force to use an index as it is causing CPU usage.
I can not change the query in application as it is used at many places.
ThanksHi,
Version is
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi
PL/SQL Release 10.2.0.5.0 - Production
CORE 10.2.0.5.0 Production
TNS for 64-bit Windows: Version 10.2.0.5.0 - Production
NLSRTL Version 10.2.0.5.0 - Production
Sorry, in my last post i forgot to mention that i already created a function based index but still it is not using because, there is a UNIQUE constraint on that column.
Thanks
Maybe you are looking for
-
Hi all I am working with a web application and I am getting the following error: Error in allocating a connection. Cause: In-use connections equal max-pool-size and expired max-wait-time. Cannot allocate more connections I understand that that means
-
Unable to pass on value to report
Hi, I have three pages: form, classic report and interactive report. I am trying to pass deptno value to deptno item created in classic report. On my form, under Actions, I am setting report's field value equal to form's field value. On clicking the
-
Creating PDF from XML directly in a content management system?
Hi! This is my first post here and I've tried to find any previous posts that could answer my question but to no avail. Also I think and hope this is the correct sub forum to post it in. I work at a company that produces a product catalogue that is p
-
Extending 27" Cinema Display A Great Distance
Hey all, I have purchased 2 cinema displays and I have my computer located about 100 feet away in a separate machine room. Normally i would buy a KVM extender to extend the display over Cat6. However since the LED cinema displays i have only have a M
-
Hi Friends, Can someone please help me out with this.Below is my Sender Data Type which needs to be converted: DT_TRAC_MESG (Hierarchy 1) TRAC_INFO (Hierarchy 2) TRAC00 (Hierarchy 2)GROUP1