Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 989061
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 16, 20262026-05-16T05:43:54+00:00 2026-05-16T05:43:54+00:00

I’m having trouble getting the correct query (oracle) for what I’m looking for. Essentially

  • 0

I’m having trouble getting the correct query (oracle) for what I’m looking for.
Essentially what I want is:

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

Explain:

| Id  | Operation                    |  Name            | Rows  | Bytes | Cost |
|   0 | SELECT STATEMENT             |                  |     1 |    14 |  3080|
|   1 |  SORT AGGREGATE              |                  |     1 |    14 |      |
|   2 |   TABLE ACCESS BY INDEX ROWID| CLAIM_KEY        |  6531 | 91434 |  3080|
|   3 |    INDEX SKIP SCAN           | I_CLAIM_KEY_001  |  1306K|       |  2813|

This query gets me what I want (the result on average being 20), but takes 10 minutes to run.

The following query is not quite complete, but runs much faster:

SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5

Explain:

| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
|   0 | SELECT STATEMENT     |             |     1 |    11 |  9195 |
|   1 |  SORT AGGREGATE      |             |     1 |    11 |       |
|   2 |   TABLE ACCESS FULL  | CLAIM_KEY   | 19592 |   210K|  9195 |

This returns about 20 as well, though this is just by fluke and I can’t rely on it, I need to include the prgrm_id. The thing is that it only take 20 seconds.

The following query is not what I’m looking for but gives an idea of the performance:

SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
| Id  | Operation             |  Name            | Rows  | Bytes | Cost  |
|   0 | SELECT STATEMENT      |                  |     1 |     8 |     4 |
|   1 |  SORT AGGREGATE       |                  |     1 |     8 |       |
|   2 |   INDEX FAST FULL SCAN| I_CLAIM_KEY_002  |   195K|  1530K|     4 |

This also takes 20 seconds, but it returns on average 700 records. The table claim_key is about 25 million rows.

There are multiple indexes on this table. They are:

IX_CLAIM_KEY_CREATED: CREATED_ON
I_CLAIM_KEY_001: CLNC_STE_ID, PRVDR_ID, PRGRM_ID, UPDATED_ON
I_CLAIM_KEY_002: SRCE_ID, PRVDR_ID, CLNC_ID, DTE_OF_SRVCE, PRGRM_ID
I_CLAIM_KEY_003: CLNT_ID, DTE_OF_SRVCE
I_CLAIM_KEY_004: TRNSMSN_ID, CLM_STTS
I_CLAIM_KEY_005: UPDATED_ON
I_CLAIM_KEY_006: PRVDR_ID, CMN_SRCE_ID
PK_CLAIM_ID: ID

What I want to know is why is adding the prgrm_id slowing it down so much? I would have expected it to be pretty quick since it would only have to search through the 700 rows specified by (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY)). Is that an incorrect assumption?

Edit

Using the hint /*+ FULL(ck) */ on the first query, its execution time drops and it generates the following plan.

| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
|   0 | SELECT STATEMENT     |             |     1 |    14 |  9195 |
|   1 |  SORT AGGREGATE      |             |     1 |    14 |       |
|   2 |   TABLE ACCESS FULL  | CLAIM_KEY   |  6531 | 91434 |  9195 |
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-16T05:43:55+00:00Added an answer on May 16, 2026 at 5:43 am

    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.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.