DBAsupport.com Forums - Powered by vBulletin
Page 1 of 3 123 LastLast
Results 1 to 10 of 30

Thread: composite index

  1. #1
    Join Date
    Jun 2000
    Posts
    295

    composite index

    Hi

    If I have a table test, which looks like:
    (col1_10...
    Indx_col1 varchar2(32),
    Indx_col2 varchar2(32))

    My query is:
    select * from test
    where Indx_col1 = 'ABC' and SUBSTR(Indx_col2, 1, 3) = 'XYZ';

    The index is used.

    If I change the above query:
    select * from test
    where Indx_col1 = 'ABC' and Indx_col2 like 'XYZ%';

    The index is also used.

    My question is:
    What is performance impact if both queries use the same index?

    Thank you!

  2. #2
    Join Date
    Dec 2002
    Location
    Bangalore ( India )
    Posts
    2,434
    logically, 2nd query wud take much time.

    Abhay.
    funky...

    "I Dont Want To Follow A Path, I would Rather Go Where There Is No Path And Leave A Trail."

    "Ego is the worst thing many have, try to overcome it & you will be the best, if not good, person on this earth"

  3. #3
    Join Date
    Aug 2002
    Location
    Colorado Springs
    Posts
    5,253
    I think it is difficult to say for sure. We know by looking at the queries that they are logically equivalent, and there is no reason why Oracle shouldn't. It could also use the index for ...

    Indx_col1 = 'ABC' and SUBSTR(Indx_col2, 2, 3) = 'XYZ'

    ... although it might use it in a different way.

    I suspect that more recent versions of Oracle will produce the same query plan and will perform the same.
    David Aldridge,
    "The Oracle Sponge"

    Senior Manager, Business Intelligence Development
    XM Satellite Radio
    Washington, DC

    Oracle ACE

  4. #4
    Join Date
    Sep 2000
    Location
    Chennai, India
    Posts
    865

    Re: composite index

    Originally posted by sysdba

    My question is:
    What is performance impact if both queries use the same index?

    Time both the queries individually...

    1. alter session set timed_statistics = true;
    2. alter session set sql_trace = true;
    3. run sql
    4. turn off sql trace & timing
    5. tkprof the trace file generated with explain.

    HTH.

  5. #5
    Join Date
    Dec 2002
    Location
    Bangalore ( India )
    Posts
    2,434
    Originally posted by slimdave
    I think it is difficult to say for sure. We know by looking at the queries that they are logically equivalent, and there is no reason why Oracle shouldn't. It could also use the index for ...

    Indx_col1 = 'ABC' and SUBSTR(Indx_col2, 2, 3) = 'XYZ'

    ... although it might use it in a different way.

    I suspect that more recent versions of Oracle will produce the same query plan and will perform the same.
    2nd query uses wildcard search with LIKE operator & that will be slow.


    Abhay.
    funky...

    "I Dont Want To Follow A Path, I would Rather Go Where There Is No Path And Leave A Trail."

    "Ego is the worst thing many have, try to overcome it & you will be the best, if not good, person on this earth"

  6. #6
    Join Date
    Dec 2000
    Location
    Ljubljana, Slovenia
    Posts
    4,439
    Originally posted by abhaysk
    2nd query uses wildcard search with LIKE operator & that will be slow.
    Wildcard search does not necesserily mean anything bad, particulary in the given example where whildcard is the last character in the LIKE expression.

    Let's see what we have:

    1) ... where Indx_col1 = 'ABC' and SUBSTR(Indx_col2, 1, 3) = 'XYZ';
    2) ... where Indx_col1 = 'ABC' and Indx_col2 like 'XYZ%';

    Based on the title of this thread I'm assuming there is a composite index INDX1(Indx_col1,Indx_col2). Now for both the above queries optimizer will probably choose INDEX RANGE SCAN operation on INDX1. But will the range of index entries being searched be equal in both cases? Probably not. In case 1) it'll have to go trough entire range of col1='ABC', because the SUBSTR function on col2 will suppress it to narrow the range to only col2 entries that begin with 'XYZ'. On the other hand, in case 2) it will directly narrow the index scan to only those leaf blocks that contain col1='ABC' and where col2 begins with 'XYZ'. So the execution plan might be exactly the same, but the number of I/O operations performed in case 1 might be much larger than that of case 2. Hence case 1 could not perform better than case 2, yet it could perform much worse! So nothing bad in using '%' in the LIKE operation like in the above example.

    Now let's say our composite index is composed like INDX2(Indx_col2,Indx_col1). In this situation, case 1) will probably be unable to use the index at all, hence it'll need to do full table scan. On the other hand, case 2) will be able to use that index. So again, notthing bad with using '%'.

    I' can see almost no situation where query 2 could perform worse than query 1 (if we do not speak about function based indexes). But I can see many situations where query 2 will significantly outperform query 1.
    Jurij Modic
    ASCII a stupid question, get a stupid ANSI
    24 hours in a day .... 24 beer in a case .... coincidence?

  7. #7
    Join Date
    Dec 2002
    Location
    Bangalore ( India )
    Posts
    2,434
    Originally posted by jmodic
    Wildcard search does not necesserily mean anything bad, particulary in the given example where whildcard is the last character in the LIKE expression.

    Based on the title of this thread I'm assuming there is a composite index INDX1(Indx_col1,Indx_col2). Now for both the above queries optimizer will probably choose INDEX RANGE SCAN operation on INDX1. 1.
    Index range scan will not be used if query contains LIKE operator....rather wud go for FTS
    so the second query wud take more time.

    Abhay.
    funky...

    "I Dont Want To Follow A Path, I would Rather Go Where There Is No Path And Leave A Trail."

    "Ego is the worst thing many have, try to overcome it & you will be the best, if not good, person on this earth"

  8. #8
    Join Date
    Nov 2002
    Location
    Geneva Switzerland
    Posts
    3,142
    Hi Abhay,
    I think you should read a bit and experiment a bit.
    Jurij knows his stuff - make sure you know yours before you pick a "fight"!
    "The power of instruction is seldom of much efficacy except in those happy dispositions where it is almost superfluous" - Gibbon, quoted by R.P.Feynman

  9. #9
    Join Date
    Nov 2002
    Location
    New Delhi, INDIA
    Posts
    1,796
    Originally posted by abhaysk
    Index range scan will not be used if query contains LIKE operator....rather wud go for FTS
    so the second query wud take more time.

    Abhay.
    Abhay check this

    Code:
    1  select  EQUIPMENT_NO,CONTAINER_IND,POO_POOL_CODE
      2  from
      3  eq_equipments
      4  where
      5  STY_EQPSIZE=20
      6  and
      7* STY_TYPE_CODE='GP'
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1547 Card=12681 Bytes=240939)
       1    0   TABLE ACCESS (BY INDEX ROWID) OF 'EQ_EQUIPMENTS' (Cost=1547 Card=12681 Bytes=240939)
       2    1     INDEX (RANGE SCAN) OF 'EQ_EQUIPMENTS_NU2' (NON-UNIQUE) (Cost=64 Card=12681)
    
    
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
      1  select  EQUIPMENT_NO,CONTAINER_IND,POO_POOL_CODE
      2  from
      3  eq_equipments
      4  where
      5  STY_EQPSIZE=20
      6  and
      7* STY_TYPE_CODE  LIKE 'GP%'
    SQL> /
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1552 Card=12711 Bytes=241509)
       1    0   TABLE ACCESS (BY INDEX ROWID) OF 'EQ_EQUIPMENTS' (Cost=1552 Card=12711 Bytes=241509)
       2    1     INDEX (RANGE SCAN) OF 'EQ_EQUIPMENTS_NU2' (NON-UNIQUE) (Cost=65 Card=12711)
    
    
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
      1  select  EQUIPMENT_NO,CONTAINER_IND,POO_POOL_CODE
      2  from
      3  eq_equipments
      4  where
      5  STY_EQPSIZE=20
      6  and
      7* SUBSTR(STY_TYPE_CODE,1,2)='GP'
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1384 Card=2283 Bytes=43377)
       1    0   TABLE ACCESS (BY INDEX ROWID) OF 'EQ_EQUIPMENTS' (Cost=1384 Card=2283 Bytes=43377)
       2    1     INDEX (RANGE SCAN) OF 'EQ_EQUIPMENTS_NU2' (NON-UNIQUE) (Cost=1117 Card=2283)
    HTH
    Amar
    "There is a difference between knowing the path and walking the path."

    Amar's Blog  Get Firefox!

  10. #10
    Join Date
    Dec 2000
    Location
    Ljubljana, Slovenia
    Posts
    4,439
    Originally posted by abhaysk
    Index range scan will not be used if query contains LIKE operator....rather wud go for FTS
    so the second query wud take more time.
    That is total and absolute nonsence. And it's so easy to prove the absurdness of your claims.

    So let's not speculate, let's test it on a simple example. First, let's create a test table with a composite index:
    Code:
    Connected to:
    Oracle8i Enterprise Edition Release 8.1.7.1.1 - Production
    With the Partitioning option
    JServer Release 8.1.7.1.1 - Production
    
    SQL> CREATE TABLE test (indx_col1, indx_col2, col3) NOLOGGING AS
      2  SELECT owner, object_name, ROWNUM FROM DBA_OBJECTS;
    
    Table created.
    
    SQL> CREATE INDEX indx1 ON test (indx_col1, indx_col2) NOLOGGING;
    
    Index created.
    
    SQL> select count(*) from test;
    
      COUNT(*)
    ----------
         38397
    
    SQL>
    Now let's see the explain plan for both queries:
    Code:
    SQL> set autotrace traceonly explain
    SQL> SELECT * FROM test
      2  WHERE Indx_col1 = 'ABC' AND SUBSTR(Indx_col2, 1, 3) = 'XYZ';
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE
       1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST'
       2    1     INDEX (RANGE SCAN) OF 'INDX1' (NON-UNIQUE)
    
    
    
    SQL> 
    SQL> SELECT * FROM test
      2  WHERE Indx_col1 = 'ABC' AND Indx_col2 LIKE 'XYZ%';
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE
       1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST'
       2    1     INDEX (RANGE SCAN) OF 'INDX1' (NON-UNIQUE)
    So, did both queries used index range scan? YES! So, did the LIKE operator suppressed the usage of index and forced a FTS? OF COURSE NOT!

    Now let's se which of the two queries (which use the same execution plan) is more efficient. We'll do this by observing the number of I/O operations each query needs to execute. let's start with the first one that uses SUBSTR function on Indx_col2:
    Code:
    set autotrace traceonly statistics
    SQL> SELECT * FROM test
      2  WHERE Indx_col1 = 'SYS'  AND SUBSTR(Indx_col2, 1, 3) = 'DBM';
    
    245 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
            105  consistent gets
              0  physical reads
              0  redo size
          14767  bytes sent via SQL*Net to client
           2323  bytes received via SQL*Net from client
             19  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
            245  rows processed
    
    SQL> /
    
    245 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
            105  consistent gets
              0  physical reads
              0  redo size
          14767  bytes sent via SQL*Net to client
           2323  bytes received via SQL*Net from client
             19  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
            245  rows processed
    
    SQL> /
    
    245 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
            105  consistent gets
              0  physical reads
              0  redo size
          14767  bytes sent via SQL*Net to client
           2323  bytes received via SQL*Net from client
             19  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
            245  rows processed
    So it repeatedly needed 105 logical I/O operation to return those 245 rows. Now let's check with the second query which uses LIKE operator for Indx_col2:
    Code:
    SQL> SELECT * FROM test
      2  WHERE Indx_col1 = 'SYS'  AND Indx_col2 LIKE 'DBM%';
    
    245 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
             39  consistent gets
              0  physical reads
              0  redo size
          14767  bytes sent via SQL*Net to client
           2313  bytes received via SQL*Net from client
             19  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
            245  rows processed
    
    SQL> /
    
    245 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
             39  consistent gets
              0  physical reads
              0  redo size
          14767  bytes sent via SQL*Net to client
           2313  bytes received via SQL*Net from client
             19  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
            245  rows processed
    
    SQL> /
    
    245 rows selected.
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
             39  consistent gets
              0  physical reads
              0  redo size
          14767  bytes sent via SQL*Net to client
           2313  bytes received via SQL*Net from client
             19  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
            245  rows processed
    So the second query with LIKE repeatedly needed only 39 logical I/O operations. So like I said, not only that it used the same execution path, it was also about 3 times more efficient!
    Jurij Modic
    ASCII a stupid question, get a stupid ANSI
    24 hours in a day .... 24 beer in a case .... coincidence?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Click Here to Expand Forum to Full Width