Oracle insists on using particular index in SELECT -- HELP!!!
Here's the situation: Back in November, I wrote a report program that contained the following SELECT statement on SAP table FMIFIIT:
* Get data from the FMIFIIT table.
SELECT trbtr
fmbelnr
fmbuzei
fonds
fistl
farea
measure
fipex
zhldt
sgtxt
grant_nbr
FROM fmifiit
INTO TABLE it_fmifiit_data
WHERE zhldt >= p_bpdte AND
zhldt <= p_epdte AND
fistl IN r_fndctr AND
fistl BETWEEN '4011000000' AND '4013999999' AND
fonds IN r_fund AND
fipex BETWEEN '500000' AND '599999' AND
measure <> 'GRANT RELEVANT' AND
measure IN s_rio AND
wrttp NOT IN ('51','60','81') AND
stats = ' '.
I ran into time-out issues with this statement, so a new index ("Z5") was created on the following fields: ZHLDT, FISTL, FONDS, and FIPEX. This was the 11th custom index added to the table. The program was re-run, the statement picked up the new index, and it ran much faster. Problem solved.
Fast-forward to this week. I wrote a new report program that used a SELECT statement virtually identical to the one above. It looks like this:
* Get FMIFIIT data.
SELECT gjahr
knbelnr
knbuzei
measure
trbtr
fmbelnr
fmbuzei
fonds
fistl
farea
fipex
zhldt
sgtxt
FROM fmifiit
INTO TABLE it_fmifiit
WHERE zhldt >= p_bpdte AND
zhldt <= p_epdte AND
fistl IN r_fndctr AND
fonds IN r_fund AND
fipex BETWEEN '500000' AND '599999' AND
measure <> 'GRANT RELEVANT' AND
measure IN s_rio AND
wrttp NOT IN ('51','60','81') AND
stats = ' '.
Again, the program began running into time-out issues on this statement. I did a trace using ST05, and I found that the system was choose index "3" (FONDS, FIPEX, FIPOS) instead of the obviously-better "Z5" index created a few months ago.
I tried all kinds of things to figure out why it was choosing "3" to no avail. Basis even re-ran statistics on the FMIFIIT table, but that didn't work. Right now, my only option is to add an Oracle hint to the SELECT statement to force it to use index "Z5". In our DEV system, I've used SE30 to verify that this definitely improves the timing bottleneck that occurs when "3" is used.
I've only been an ABAP programmer for a few years now, and this one is technically beyond my knowledge. I don't know what else to try, and I don't know how to determine why the system keeps choosing the index it does. It's especially frustrating when the SELECT statement is so similar to the one from above, and in that case, it DOES pick up the "Z5" index.
Does anyone have any information/strategies/suggestions? At this point, I'm all ears.
Thanks so much!
Dave
Hi Dave,
based on the query I cannot share your view that there is an obvious choice.
In fact the best index choice depends on what your data looks like and how are the In-lists filled.
Maybe the range conditions are very useful, maybe the in-lists are the most selective criteria.
As a detailed analysis of this is a bit heavy to be done via this forum, why don't you just implement the hint and live happily with it?
Since you find your index sensible and have proven that it leads to better performance, you obviously know more about your data than Oracle does by the statistics.
Now you can either try and learn how the Oracle CBO works (there are notes and books available on this topic) or you just use your workaround although you may not exactly understand the reasons for the problem.
In general - if this would be a support message - I would ask you to ensure that all parameter recommendations are implemented and all CBO patches are installed.
Then I'd use the sql-statement data collection script (there's a sap note containing this script - just search for 'sql_id') to gather much of the relevant data.
And then I'd have to look into the data and figure out what's behind the CBOs decision.
As you wrote that you're rather on the ABAP side of live this effort may not necessarily be worthwhile when you have a proven workaround at hand.
regards,
Lars
Similar Messages
-
Which queries using particular index?
Hello,
Is it possible in Oracle 11gR2 to find out which queries are using or used particular INDEX?
Thanks a lot for your suggestion.
Best RegardsHello,
Thanks a lot.
I have queried what you suggested, and got 5 sql_ids, but I quickly got the EXPLAIN PLAN for all the 5 sql_ids after getting sql_text, but the index I am looking for is not in the NAME column of select * from table (dbms_xplan.display());
select distinct(sql_id) from v$sql_plan where object_owner = 'HEMANT' and object_name = '&myindex';
I am little confused now, as v$sql_plan showing 5 sqls based on myindex but no one is actually using index?
Thank you.
Best Regards -
Use of Indexes in select query
Hello,
This is on a 9i install.
There is an index called form_id_idx on the form_id column.
Why does this query use the index (autotrace indicates range scan on the index):
select count(*) from table_name where form_id=123456;
but this query does NOT use the index (autotrace indicates full table scan):
select accepted from table_name where form_id=123456;
This second query runs much faster when I use a hint on the index. Any help/suggestions?
Thanks.The first query does NOT have to go to the Table it all. It can read the index to count the number of rows for "form_id=123456". An Index Range Scan would be fast.
The second query has to go to the table to get the values for the "accepted" column for all the rows that have "form_id=123456". Remember that every get can require a read of 2 or more blocks -- at least one, probably 2 or 3, from the index and 1 from the table. If the number of rows is likely to be large then the number of block get operations would be high. In such cases, Oracle computes that it is faster to do a small set of multiblock reads to read the whole table (Table FullScan).
Therefore, the optimzer weighs :
a. how many rows it thinks will satisfy "form_id=123456"
b. how many index + table block gets it would have to execute (all as single block read calls to the OS)
versus
x. how many multiblock read calls it thinks it has to execute to read the whole table
If the available statistics on number of rows, cardinality or density and the size of the table indicate that operation "x" would be cheaper then operations "a" + "b", Oracle would prefer the latter.
Hemant K Chitale
http://hemantoracledba.blogspot.com -
EL expression to set row at particular index as selected row
Hi,
What should be the EL expression to set row at index 'i' as selected row in a tree binding.
I tried *#{bindings.treeBinding.collectionModel.selectedRow[i]}* . But it doesn't work.
I also want to make the selected row as current. Will *#{bindings.treeBinding.collectionModel.makeCurrent}* work?
Thanks
KKHi,
create a managed bean that returns the selected RowKeys for the tree. See this example:
http://www.oracle.com/technetwork/developer-tools/adf/learnmore/61search-in-rendered-trees-177577.pdf
It searches for a specific label in a tree and marks it as selected
Frank -
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.
-
How to force the optimaizer to stop using an index ?
Hello,
I have an index on a very large table and I want to see how the applications running on this DB handles a situation in which this index does not exists.
Therfore I have 2 options:
1. drop the index - but this is too risky as if i will need to recreate it , it will last forever and will result in long application downtime which I can not afford.
The test and Dev environments does not contain ammounts of data like the prodicution so its hard to predict from these environments.
2. the second option is Modify the index columns statistics (which I have done) giving it low NDV (number of diftinct values) -- but sadly this did not work.
when cheking event 10053 I see a the line "Using prorated density: [ 1/(2*num_rows) ] of col #n as selectivity of out-of-range value pred" which I guess meens the High value of the column is lower then the value given it the query ( I do not run statistics every day , the current statistics for all columns (execpt this one ) suits best and I do not want to handle plan changes . also it will take a lot of time to gather table stats on daily basis.
So - to make a long story short - how do I force Oracle to avoid using an index but continue builing it and without dropping it?
I can not use the 'NO_INDEX' hint as it will requre change in many Applications.
I don need something like NO_INDEX hint on system level.
I am using Oracle 10g Enterprise edition.
the optimaized_mode is set to COST BASED.
Thanks in advance for any help resolving this complicated issue.
Regards,
Amit Zor.
ADBA.user3698066 wrote:
Hello,
I have an index on a very large table and I want to see how the applications running on this DB handles a situation in which this index does not exists.
2. the second option is Modify the index columns statistics (which I have done)
I'm still wondering if there is a way of modifying the statistics of the index in such a way so that it is not used by the optimizer.
Since the main contributors of the formula for an simple b-tree index access path are the height of index, the number of leaf blocks and for the table access the clustering factor, may be you could come up with all those values bumped up to very large values for that particular index.
Unfortunately the only component of the formula that is not multiplied by a factor is the height of the index, which is sanity checked (at least in 10.2) when set manually and is limited to a (already quite unreasonable) 255, so you can't set it greater than 255, but the remaining attributes can be set more or less to whatever you want.
So you could come up with an manual modification of the index statistics like this. Note that I don't modify the NUM_ROWS and DISTINCT_KEYS values in an attempt to limit the risk of unwanted side effects of this modification.
begin dbms_stats.set_index_stats(
ownname=>'<index_owner>,
indname=>'<index_name>',
indlevel=>255,
numlblks=>1000000000,
clstfct=>1000000000,
avglblk=>1000000000/<num_distinct>,
avgdblk=>1000000000);
end;
/In a quick test I was successfully able to prevent a very selective index access path using these settings, but depending on your remaining statistics and the access paths chosen by the optimizer this might not work for you, at least not in all possible cases, e.g. an index unique scan won't cost more than 256 even using these settings because only a single leaf block by definition has to be visited in this case.
Of course I haven't checked thoroughly what other side effects this statistics fudging does have, so use at your own risk resp. test it in your non-production environment before even thinking about applying it to an production system.
Regards,
Randolf
Oracle related stuff blog:
http://oracle-randolf.blogspot.com/
SQLTools++ for Oracle (Open source Oracle GUI for Windows):
http://www.sqltools-plusplus.org:7676/
http://sourceforge.net/projects/sqlt-pp/ -
Use of Index, Histograms, etc
Hi all,
We're using Oracle 9.2.04.
I have a table with 500000 rows.
So I have a query that returns only 30242 for a month, like:
SELECT * FROM T1
WHERE TO_CHAR(DT, 'MM/YYYY') = TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'MM/YYYY')
I have a index for this column:
CREATE INDEX IND_T1_DT_FMT ON T1 (TO_CHAR(DT, 'MM/YYYY'))
TABLESPACE TBS_SOME_USER;
There are statistics for this table.
Looking the table data, I have the following distribution:
Qty MON/YY %
1 Feb-09 0.000219142
99 Apr-09 0.021695016
38439 May-09 8.42358314
98231 Jun-09 21.52649641
1 Jul-06 0.000219142
139959 Jul-09 30.6708362
1 Aug-02 0.000219142
1 Aug-07 0.000219142
141362 Aug-09 30.97829184
30242 Sep-09 6.62727962
7990 1.750941213But when a perform the query (that returns 30242 rows - 6.63% of table):
SELECT * FROM T1
WHERE TO_CHAR(DT, 'MM/YYYY') = TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'MM/YYYY')
Oracle uses FTS:
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=432 Card=45633 Bytes
=3011778)
1 0 TABLE ACCESS (FULL) OF 'T1' (Cost=432 Card=45633 Bytes
=3011778)
So, Oracle should not use the index in this case?
Is there any way to gather statistics for this table with a index based function?
Something like this:
EXECUTE DBMS_STATS.GATHER_TABLE_STATS(ownname => 'U1',
tabname => 'T1', method_opt => 'FOR COLUMNS TO_CHAR(DT, ''MM/YYYY'')',
cascade => true, degree => 4);
How can I create histograms for this case?
Or other solution, like Partition?
thank you very much!!!!Always treat dates like dates.
This
SELECT * FROM T1
WHERE TO_CHAR(DT, 'MM/YYYY') = TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'MM/YYYY')Should be more like this:
SELECT * FROM T1
WHERE DT BETWEEN TRUNC(ADD_MONTHS(SYSDATE,-1),'MM') AND TRUNC(SYSDATE,'MM')-1 ;Then you should index DT.
But, should this query use the index?
Touch and go at 6.63%.
Give it a go using dates as dates and see if it makes a difference.
Is there a problem with the performance of the FTS? -
Restrict the use of index while quering
Hi All
I have a simple emp table with columns empid, name, sal. Empid has a primary key imposed.
Now when i write a statement like this,
select * from emp where empid = <value>;
the optimizer will make use of index.
The question is........... is there anyway to make oracle bypass the use of index without change in above query.Why do you worry of performance issues when the table size is small , when it is huge and the column you r trying use in the query is also indexed the oracle finds the Best execution method to do the execution whether index exists or not , Oracle has a very intelligent Optimizer and no need to use hints unless and until it is really mandatory or when u r using a very complex query where Oracle is not able to deduce the best Execution plan . But by all means you should look at the execution plan how a cerain query Oracle knows of doing it or when u have a diferering opinion then only at that point you force a Optomizer Hint . For other normal cases like the one you are asking it is best to get the results how Oracle executes it and no forcing is required .
-
Rule-Based Optimizer doesn4t use the index
Does anybody know why the rule-based optimizer doesn4t use the index of all columns in the where clause?
I have a select that use the hint RULE to force the optimizer to work in rule mode and also one index to all columns used in the where clause. Analyzing the execution plan (EXPLAIN PLAN) I observed the optimizer accesses all tables, but one, using the index. There4s one table (the first of the execution plan) that is accessed using a Full Table Scan (FTS).
I've rebuilt the index for this table, but the execution plan doesn4t change.
Any suggestions?
Thanks in advance.
Eliane.Hi. Oracle may not use an index if it finds that a full table scan is quicker/more efficient. Try the hint /*+ INDEX (table index) */ and compare the query performance with that of the one without this hint. (As you know, if you force Rule-based approach, the COST column in EXPLAIN PLAN output will not be populated. You may have to use trace/tkprof.)
-
Simple query but not using index..please help??
I do have this column indexed. Why my query is not using this index?
Any help .
select count(*) from v_dis_sub_har;
SQL>
COUNT(*)
4543289
1 row selected.
SQL>
select vzw_vendor_id , count(*)
from v_dis_sub_har
group by vzw_vendor_id
SQL> 2 3 4
VZW_VENDOR_ID COUNT(*)
200091 908653
200013 908659
200012 908659
200057 908659
200031 908659
5 rows selected.
SQL> SQL>
explain plan for
select
event_seq
from v_dis_sub_har b
where b.VZW_VENDOR_ID='200013'
-- and b.status='P' and b.extract_date is null
SQL> 2 3 4 5 6 7
Explained.
SQL> SQL>
select plan_table_output from table(dbms_xplan.display)
SQL> SQL> 2
PLAN_TABLE_OUTPUT
Plan hash value: 2852398983
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 908K| 7986K| 3132 (16)| 00:00:38 |
|* 1 | TABLE ACCESS FULL| V_DIS_SUB_HAR | 908K| 7986K| 3132 (16)| 00:00:38 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter("B"."VZW_VENDOR_ID"=200013)
13 rows selected.
SQL> SQL>You are right Justin. Oracle is not stupid as you may want to say some times when things do not happen according to you. I just created a bitmap index on status field and look what appened. Som times it uses bitmap index and some times it does not. And the reason is clear. Row count by status. 'S' status uses bitmap index where 'P' does not.
Thanks for your help.
select status, count(*)
from v_dis_sub_har
group by status
;SQL> 2 3 4
S COUNT(*)
A 5844982
P 2312759
S 20178
3 rows selected.
SQL>
explain plan for
select
event_seq
from v_dis_sub_har b
where
--b.VZW_VENDOR_ID=200013
-- and
b.status='S'
--and b.extract_date is null
select plan_table_output from table(dbms_xplan.display)
SQL> 2 3 4 5 6 7 8 9 10
Explained.
SQL> SQL> SQL> SQL> 2
PLAN_TABLE_OUTPUT
Plan hash value: 829738689
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T
ime |
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | 20290 | 118K| 2772 (1)| 0
0:00:34 |
| 1 | TABLE ACCESS BY INDEX ROWID | V_DIS_SUB_HAR | 20290 | 118K| 2772 (1)| 0
0:00:34 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | |
|
|* 3 | BITMAP INDEX SINGLE VALUE | V_DISPATCH_SUBSCRIPTION_NDX2 | | | |
|
PLAN_TABLE_OUTPUT
Predicate Information (identified by operation id):
3 - access("B"."STATUS"='S')
15 rows selected.
SQL> SQL> set line 120
SQL> /
PLAN_TABLE_OUTPUT
Plan hash value: 829738689
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 20290 | 118K| 2772 (1)| 00:00:34 |
| 1 | TABLE ACCESS BY INDEX ROWID | V_DIS_SUB_HAR | 20290 | 118K| 2772 (1)| 00:00:34 |
| 2 | BITMAP CONVERSION TO ROWIDS| | | | | |
|* 3 | BITMAP INDEX SINGLE VALUE | V_DISPATCH_SUBSCRIPTION_NDX2 | | | | |
PLAN_TABLE_OUTPUT
Predicate Information (identified by operation id):
3 - access("B"."STATUS"='S')
15 rows selected.
SQL>
explain plan for
select
event_seq
from v_dis_sub_har b
where
--b.VZW_VENDOR_ID=200013
-- and
b.status='P'
--and b.extract_date is null
select plan_table_output from table(dbms_xplan.display)
SQL> 2 3 4 5 6 7 8 9 10
Explained.
SQL> SQL> SQL> SQL> 2
PLAN_TABLE_OUTPUT
Plan hash value: 2852398983
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 2325K| 13M| 5784 (18)| 00:01:10 |
|* 1 | TABLE ACCESS FULL| V_DIS_SUB_HAR | 2325K| 13M| 5784 (18)| 00:01:10 |
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
1 - filter("B"."STATUS"='P')
13 rows selected.
SQL> -
UPPER Indexes cause select ERROR!
I downloaded Oracle 10g and installed it on a windows 2003 server. When I created UPPER indexes on a table, and the table has many rows, SELECT statement failed.
for example:
DROP TABLE TestTab;
CREATE TABLE TestTab(
id NUMBER(9) DEFAULT 1 NULL,
name VARCHAR2(32) NULL,
address VARCHAR2(64) NULL,
PRIMARY KEY (id)
DROP INDEX TestTab_01;
CREATE INDEX TestTab_01 ON TestTab(UPPER(name));
DROP INDEX TestTab_02;
CREATE INDEX TestTab_02 ON TestTab(UPPER(address));
create or replace procedure ADDDATA
IS
lCount NUMBER;
BEGIN
lCount := 1;
LOOP
INSERT INTO TESTTAB VALUES(lCount, TO_CHAR(lCount, '00000'), TO_CHAR(lCount, '00000'));
lCount := lCount + 1;
IF lCount >= 80000 THEN
EXIT;
END IF;
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
EXEC ADDDATA;
SELECT COUNT(*) FROM TestTab;
SELECT id FROM TestTab WHERE (UPPER(name) = ' 00100' OR UPPER(name) = ' 00101' OR UPPER(name) = ' 00102'
OR UPPER(address) = ' 00105' OR UPPER(address) = ' 00106') ORDER BY id;
ID
100
101
102
SELECT id FROM TestTab WHERE (UPPER(address) = ' 00105' OR UPPER(address) = ' 00106' OR UPPER(name) = ' 00100' OR UPPER(name) = ' 00101' OR UPPER(name) = ' 00102') ORDER BY id;
ID
105
106
It looks like that the first index could be used and the second index couldn't be used and indexes caused select errors.indexes caused select errors. Which errors ? I did exactly what you posted, and these are the results :
TEST@db102 SQL> SELECT id FROM TestTab WHERE (UPPER(name) = ' 00100' OR UPPER(name) = ' 00101' OR UPPER(name) = ' 00102'
OR UPPER(address) = ' 00105' OR UPPER(address) = ' 00106') ORDER BY id; 2
ID
100
101
102
105
106
TEST@db102 SQL> SELECT id FROM TestTab WHERE (UPPER(address) = ' 00105' OR UPPER(address) = ' 00106' OR UPPER(name) = ' 00100'
OR UPPER(name) = ' 00101' OR UPPER(name) = ' 00102') ORDER BY id;
ID
100
101
102
105
106
TEST@db102 SQL> select count(*) from testtab;
COUNT(*)
79999
TEST@db102 SQL> -
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 AMIf 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. -
Selecting all columns makes oracle use more indexes than only selectng one?
I have 3 queries here that differ only slightly, conceptually, but the plans are massively different. What I cant work out is that the difference is only in the select list.. The fields referenced in the where clause are properly indexed for this purpose
SELECT
scc.expiry_date
FROM
bw3.int_file_log_details ifld
INNER JOIN
bw3.svc_card_status_change scsc
USING
(institution_number, file_number)
INNER JOIN bw3.svc_client_cards scc
USING
(card_number)
WHERE
institution_number = '00000001' AND
file_number = '00002504'This one above does a full table scan of SCC, over 3.5 million records
SELECT
card_number
FROM
bw3.int_file_log_details ifld
INNER JOIN
bw3.svc_card_status_change scsc
USING
(institution_number, file_number)
INNER JOIN bw3.svc_client_cards scc
USING
(card_number)
WHERE
institution_number = '00000001' AND
file_number = '00002504'This one above does an index fast full scan of SCC's pk (which is cardnumber), as does doing a "SELECT null as dummy FROM..."
SELECT
FROM
bw3.int_file_log_details ifld
INNER JOIN
bw3.svc_card_status_change scsc
USING
(institution_number, file_number)
INNER JOIN bw3.svc_client_cards scc
USING
(card_number)
WHERE
institution_number = '00000001' AND
file_number = '00002504'This one above does the index range scan of the columns mentioned in the where clause and two index unique scans to link in IFLD and SCC (because they are joined on their PKs)
I would expect all queries to run this way and completes in ~0.01 seconds
Now, I get that oracle will sometimes use only an index instead of a table access when the requested data can be got from the index, but the actual query is pulling data from some columns not in indexes, so must be accessed in the table:
SELECT
scsc.card_prod_data as "Field1",
substr(card_number,1,4)||' '||
substr(card_number,5,4)||' '||
substr(card_number,9,4)||' '||
substr(card_number,13,4)||' '||
substr(card_number,17) as "Field2",
' ' as "Field3",
scc.emboss_line_1 as "Field4",
scc.emboss_line_2 as "Field5",
TO_CHAR(TO_DATE(scc.last_issued_date, 'YYYYMMDD'), 'MM/YY ')||
TO_CHAR(TO_DATE(scc.expiry_date, 'YYYYMMDD'), 'MM/YY ')||
' ' as "Field6",
'B'||
card_number||
'^'||
RPAD('0', 27, ' ')||
'^'||
to_char(to_date(scc.expiry_date, 'YYYYMMDD'), 'YYMM')||
service_category_code||
'000000000000' as "Field7",
card_number||
'='||
to_char(to_date(scc.expiry_date, 'YYYYMMDD'), 'YYMM')||
service_category_code||
'000000000000' as "Field8",
card_number as "Field9",
scsc.cvv_cvc2 as "Field10"
FROM
bw3.int_file_log_details ifld
INNER JOIN
bw3.svc_card_status_change scsc
USING
(institution_number, file_number)
INNER JOIN bw3.svc_client_cards scc
USING
(card_number)
WHERE
institution_number = '00000001' AND
file_number = '00002504'This query above, which uses some data from all tables, does a table full scan of SCC, yet if I SELECT * FROM.. I get the expected index usage and table access by index rowid for all tables..
Why is oracle doing an FTS when I choose only some columns, yet doing index access when I select * ?
Edited by: charred on Oct 5, 2010 11:37 AMSelectivity of indexes?
For a query linking these tables:
int_file_log_details <-> svc_card_status_change <-> svc_client_cards
I'm expecting Oracle to:
Use an index range scan of the index on svc_card_status_change that is a nonunique index of institution_number and file number. Selectivity of this index is:
1 institution number in the entire table
59 distinct file numbers in the entire table
4.1million records in the entire table
From there, with the records it found, to use index unique scan of the PKs of int_file_log_details (file_number: 1 record required) and PK of svc_client_cards (card_number: poetntially thousands of records required)
I can understand if oracle might decide it can get 69k records out of 4.1 million faster by FTS the cards table rather than having the indirection of the index... what I cannot understand is:
If I select all the data from the query (SELECT *) it does unique index scans for the 2 records
If I select say, only one non-indexed non-joined column from each table, oracle prefers a FTS of the cards table..
Is oracle not realising that there are only 2 records I need out of cards? Why would select * differ? Is it that oracle thinks "select * is a large amount of data, so it'll be faster to use the index and target certain rows" vs "select one_column can be garnered more quickly by scanning the table and generating a lower overall memory load" ? -
How to specify a particular index for DB2 database when using SQL in ABAP
Is this format for Oracle?
select *
into -
from vbrk CLIENT SPECIFIED
where erdat in erdat
and mandt EQ sy-MANDT
%_HINTS ORACLE 'INDEX("VBRK" "VBRK~ZER")'
For the index 'VBRK~ZER' was defined before,it only includes one field 'VBRK-ERDAT'.
How can i tell Sap to use this index while processing SQL in DB2?
Thanks advance.There are different hints for the different database platforms.
For up-to-date information please read the SAP notes, search 'hint DB2'.
Siegfried -
How to prevent Oracle from using an index when joining two tables ...
How to prevent Oracle from using an index when joining two tables to get an inline view which is used in an update statement?
O.K. I think I have to explain what I mean:
When joining two tables which have many entries sometimes it es better not to use an index on the column used as join criteria.
I have two tables: table A and table B.
Table A has 4.000.000 entries and table B has 700.000 entries.
I have a join of both tables with a numeric column as join criteria.
There is an index on this column in table A.
So I instead of
where (A.col = B.col)I want to use
where (A.col+0 = B.col)in order to prevent Oracle from using the index.
When I use the join in a select statement it works.
But when I use the join as inline view in an update statement I get the error ORA-01779.
When I remove the "+0" the update statement works. (The column col is unique in table B).
Any ideas why this happens?
Thank you very much in advance for any help.
Regards HartmutI think you should post an properly formatted explain plan output using DBMS_XPLAN.DISPLAY including the "Predicate Information" section below the plan to provide more details regarding your query resp. update statement. Please use the \[code\] and \[code\] tags to enhance readability of the output provided:
In SQL*Plus:
SET LINESIZE 130
EXPLAIN PLAN FOR <your statement>;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);Usually if you're using the CBO (cost based optimizer) and have reasonable statistics gathered on the database objects used the optimizer should be able to determine if it is better to use the existing index or not.
Things look different if you don't have statistics, you have outdated/wrong statistics or deliberately still use the RBO (rule based optimizer). In this case you would have to use other means to prevent the index usage, the most obvious would be the already mentioned NO_INDEX or FULL hint.
But I strongly recommend to check in first place why the optimizer apparently seems to choose an inappropriate index access path.
Regards,
Randolf
Oracle related stuff:
http://oracle-randolf.blogspot.com/
SQLTools++ for Oracle:
http://www.sqltools-plusplus.org:7676/
http://sourceforge.net/projects/sqlt-pp/
Maybe you are looking for
-
PR/PO Controlling Using FM
We're trying to control PR/PO creation using Funds Management. Right now we're doing the basic FM setup (following buidling block configuration guide 951 - Funds Management-Basic Settings). Can someone please outline the necessary steps to achieve th
-
Hi, Please let me know if there are any solutions to this or any forum topics relating to this. 1) Wscompile doesn't understand abstract="true". So the generated java source is not an abstract class. <complexType name="WSMessage" abstract="true"> W
-
T430 DisplayPort doesn't show pre-boot display
We have T430's (and X230's for that matter) connected to L2251x's via a Mini Dock Plus 3. We also have McAfee SafeBoot installed, which has a pre-boot password prompt before hitting the Windows 7 OS. No matter what we do, we cannot output this pre-bo
-
Iphone is disabled connect to itunes iphone 5
iphone is disabled connect to itunes iphone 5
-
I am doing a report where I would like to select records year to date. My difficulty is that the date field is in epoch time from 1/1/1990. What would be the formula for this record selection? I know I could use yeartodate and dateadd but am having t