tags:

views:

111

answers:

5
+1  A: 

Looks to me like none of the indexes shown in your post are very useful. I'd expect it to do a full table scan no matter what.

If you can, add an index on

DTE_OF_SRVCE, CLM_TYPE, PRGRM_ID

and see if that helps. If you want to try for an index-only retrieval, add ID to the end of the index (so it'd be DTE_OF_SRVCE, CLM_TYPE, PRGRM_ID, ID).

Share and enjoy.

Bob Jarvis
Thanks for the advice. But as it always seems I don't have the authority to create an index.
The_Denominater
A: 

Maybe it's because cInt_id is only on your third index. And else it would use the second one

Xavier Combelle
+4  A: 

To better understand what's going on, try this:

explain plan set statement_id = 'query1' for
SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5
     AND ck.prgrm_id = 1;

and then:

select *
from table(dbms_xplan.display(statement_id=>'query1'));

I'm guessing you'll see a line indicating TABLE ACCESS FULL on claim_key.

Then try:

explain plan set statement_id = 'query2' for
SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5;

select *
from table(dbms_xplan.display(statement_id=>'query2'));

and check to see what index it (presumably) using. That should give you an idea of what the database is doing which helps to figure out why it's doing it.


Ok, given your explain plans, it's a classic example of "indexes are not always good, tables scans are not always bad".

The INDEX SKIP SCAN is where the database can try to use an index even though the leading column of the index is not even used. Basically if your index looked like this (overly simplified):

COL1   COL2   ROWID
A      X      1        <--
A      Y      2
A      Z      3
B      X      4        <--
B      Y      5
B      Z      6 

and your condition was WHERE col2 = 'X' the index skip scan says look through each combination in COL1 for where col2 = 'X'. It "skips" the values in col1 once it's found a match (e.g. col1 = A, col2 = X) down to where the value changes (col1 = B, then col1 = C, etc.) and looks for more matches.

The catch is that indexes (generally!) work like this: 1) find the next rowid in the index where the value was found 2) go to the table block with that rowid (TABLE ACCESS BY INDEX ROWID) 3) repeat until no more matches are found.

(For the skip scan, it would also incur the cost of finding out where the next change of value is for the leading columns.)

This is all well and good for a small number of rows, but suffers from the law of diminishing returns; it's not that great when you've got a large number of rows. That's because it has to read an index block, then a table block, then an index block, a table block (even if the table block was previously read.)

The full table scan just "plows" through the data thanks in part to...multiblock reads. The database can read many blocks from disk in a single read and doesn't read the same block more than once.

The INDEX FAST FULL SCAN is basically treating the I_CLAIM_KEY_002 as a table. All of what you need in the query can be answered by the index alone; no TABLE ACCESS is required. (I'm guessing I_CLAIM_KEY_002 is defined as clnt_id, dte_of_srvce and either clnt_id or dte_of_srvce is not nullable. Since ck.id should be a not null attribute, a count on ck.id is the same as a count on ck.clnt_id.)

So as for your initial query, unless you want to rejig your indexes, try this:

SELECT  /*+ FULL(ck) */ count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5
     AND ck.prgrm_id = 1

which will force a full table scan on claim_key (ck) and you could see similar performance as the other two. (Check that this is the case first prefixing the query with "explain plan set statement_id = 'query_hint' for" and running the dbms_xplan query before you run it.)

(Now you'll ask "do I want to put in hints like that all the time"? Please don't. This is for a test only. This is just to check to see if a FTS is better than the INDEX SKIP SCAN. If it is, then you need to find out why. :)

Anyways...I hope that made snese..I mean sense.

Patrick Marchand
Hey, when running the second half of the first query I get a "missing right parenthesis" error under the "="? I"m not familiar with your syntax, do you know why?
The_Denominater
AFAIK you can't use named parameter notation within SQL queries. Try `select * from table(dbms_xplan.display('PLAN_TABLE','query1'))`
Dave Costa
The above syntax for the dbms_xplan was actually tested on 11g, so I apologize if it's not backwards compatible. The syntax suggested by @Dave Costa is probably the way to go in 10g.
Patrick Marchand
Hey, thanks. I've never used explain before. I've included the results, do you mind explaining them? http://pastebin.com/1PacyWAb
The_Denominater
Instead of a link in a comment, could you update your question with the explain plans, for each query? Oh, and format as code within SO.
Shannon Severance
Wow, thanks for all your help. You were right, adding the hint brings the query up to the same speed as the other two formats. This is all surpassing my knowledge of SQL, do you know of any references to read to better understand what's going on? If you recommend not using hints all the time what's the alternative, modifying the index? Thanks again for all your help.
The_Denominater
I'd be interested in seeing the plan with the hint, to see what the estimated row count is (in the Rows column.) It could simply be a case where you need to get statistics updated.FYI, the trouble with hints is that once their in, you could prevent the optimizer from choosing a better plan as things change (like data volume.)As for books, check http://stackoverflow.com/questions/989984/what-is-a-good-oracle-reference-book-for-a-beginner for some good ideas.
Patrick Marchand
A: 

Perhaps stating the obvious here, but are these results repeatable, or did you try this once, in the order specified in your question? If so then block caching could explain the differences.

DCookie
Yes, they are repeatable. Sorry, I'm not familiar with what you mean by block caching?
The_Denominater
The DB cached the results of your first query.
JNK
Oh, ok. No it's definitely not that.
The_Denominater
A: 

What happens if you try something like...

SELECT COUNT(*)
    FROM (SELECT ck.id,
                 ck.prgrm_id AS prgrm_id
              FROM claim_key ck
              WHERE (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY)) AND
                    ck.clm_type = 5) AS sq
    WHERE sq.prgrm_id = 1;

I can't try this sort of thing at home so it may be no good, but it may help.

Brian Hooper
I actually already tried that. Exact same result, it still takes about 10 minutes to run.
The_Denominater
What are the CLAIM_KEY and I_CLAIM_KEY_001?
Brian Hooper