sql >> Databasteknik >  >> RDS >> Oracle

Hur kan jag få ett COUNT(col) ... GROUP BY för att använda ett index?

Jag har haft chansen att leka med detta, och mina tidigare kommentarer angående NOT IN är en röd sill i det här fallet. Det viktigaste är närvaron av NULL, eller snarare om de indexerade kolumnerna INTE har NULL-begränsningar.

Detta kommer att bero på vilken version av databasen du använder, eftersom optimeraren blir smartare för varje release. Jag använder 11gR1 och optimeraren använde indexet i alla fall utom ett:när båda kolumnerna var null och jag inte inkluderade NOT IN klausul:

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

Utan NOT IN-satsen...

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>

När jag dobbade NOT IN klausul tillbaka i, valde optimeraren att använda indexet. Konstigt.

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>

Bara för att upprepa, i alla andra fall, så länge som en av de indexerade kolumnerna förklarades inte noll, användes indexet för att tillfredsställa frågan. Detta kanske inte stämmer på tidigare versioner av Oracle, men det pekar förmodligen vägen framåt.



  1. Fixa "ERROR 3942 (HY000):Varje rad i en VALUES-sats måste ha minst en kolumn" när du använder VALUES-satsen i MySQL

  2. Hur kan jag konvertera ett namn till id

  3. Kan inte ansluta till databasen efter några gångers driftsättning på servern

  4. välj det sista konversationsmeddelandet för varje konversation i mysql