sql >> Database >  >> RDS >> Oracle

Hoe kan ik een COUNT (col) ... GROUP BY krijgen om een ​​index te gebruiken?

Ik heb de kans gehad om hiermee te spelen, en mijn eerdere opmerkingen over de NOT IN zijn in dit geval een rode haring. Het belangrijkste is de aanwezigheid van NULL's, of beter gezegd of de geïndexeerde kolommen GEEN NULL-beperkingen hebben.

Dit zal afhangen van de versie van de database die je gebruikt, omdat de optimizer met elke release slimmer wordt. Ik gebruik 11gR1 en de optimizer gebruikte de index in alle gevallen behalve één:wanneer beide kolommen nul waren en ik de NOT IN niet had opgenomen clausule:

SQL> desc big_table
 Name                                  Null?    Type
 -----------------------------------  ------    -------------------
 ID                                             NUMBER
 COL1                                           NUMBER
 COL2                                           VARCHAR2(30 CHAR)
 COL3                                           DATE
 COL4                                           NUMBER

Zonder de NOT IN-clausule...

SQL> explain plan for
  2      select col4, count(col1) from big_table
  3      group by col4
  4  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 1753714399

----------------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           | 31964 |   280K|       |  7574   (2)| 00:01:31 |
|   1 |  HASH GROUP BY     |           | 31964 |   280K|    45M|  7574   (2)| 00:01:31 |
|   2 |   TABLE ACCESS FULL| BIG_TABLE |  2340K|    20M|       |  4284   (1)| 00:00:52 |
----------------------------------------------------------------------------------------

9 rows selected.


SQL>

Toen ik de NOT IN . deed clausule terug in, heeft de optimizer ervoor gekozen om de index te gebruiken. Raar.

SQL> explain plan for
  2      select col4, count(col1) from big_table
  3      where col1 not in (12, 19)
  4      group by col4
  5  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 343952376

----------------------------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        | 31964 |   280K|       |  5057   (3)| 00:01:01 |
|   1 |  HASH GROUP BY        |        | 31964 |   280K|    45M|  5057   (3)| 00:01:01 |
|*  2 |   INDEX FAST FULL SCAN| BIG_I2 |  2340K|    20M|       |  1767   (2)| 00:00:22 |
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------

   2 - filter("COL1"<>12 AND "COL1"<>19)

14 rows selected.

SQL>

Gewoon om te herhalen, in alle andere gevallen, zolang een van de geïndexeerde kolommen niet nul werd verklaard, werd de index gebruikt om aan de zoekopdracht te voldoen. Dit is misschien niet het geval in eerdere versies van Oracle, maar het wijst waarschijnlijk de weg vooruit.



  1. Moet ik mijn DB normaliseren of niet?

  2. MySQL-prestaties bij bestellen op berekende kolom

  3. Selecteer Som uit twee samengevoegde tabellen

  4. MySQL-schemanaam met streepje staat me niet toe om opdrachtregelquery uit te voeren