sql >> Database teknologi >  >> RDS >> Oracle

Hvordan kan jeg få et COUNT(col) ... GROUP BY for at bruge et indeks?

Jeg har haft chancen for at lege med dette, og mine tidligere kommentarer vedrørende NOT IN er en rød sild i dette tilfælde. Det vigtigste er tilstedeværelsen af ​​NULL'er, eller rettere sagt om de indekserede kolonner IKKE har håndhævet NULL-begrænsninger.

Dette kommer til at afhænge af den version af databasen, du bruger, fordi optimeringsværktøjet bliver smartere med hver udgivelse. Jeg bruger 11gR1, og optimeringsværktøjet brugte indekset i alle tilfælde undtagen ét:når begge kolonner var nul, og jeg ikke inkluderede NOT IN klausul:

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

Uden NOT IN-klausulen...

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>

Da jeg dobbede NOT IN klausul tilbage i, valgte optimeringsværktøjet at bruge indekset. Underligt.

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>

Bare for at gentage, i alle andre tilfælde, så længe en af ​​de indekserede kolonner blev erklæret ikke nul, blev indekset brugt til at tilfredsstille forespørgslen. Dette er muligvis ikke sandt på tidligere versioner af Oracle, men det peger sandsynligvis vejen frem.



  1. Hvad er @@SERVICENAME i SQL Server?

  2. Få alt efter og før bestemte tegn i SQL Server

  3. mySQL CAST og ASC/DESC

  4. Hvordan finder man et tidsdelta af en datatime-række i mysql?