sql >> Databáze >  >> RDS >> Oracle

Jak mohu získat COUNT(sloupec) ... GROUP BY pro použití indexu?

Měl jsem možnost si s tím pohrát a moje předchozí komentáře týkající se NOT IN jsou v tomto případě červeným sledem. Klíčovou věcí je přítomnost hodnot NULL, nebo spíše to, zda indexované sloupce nemají vynucená omezení NULL.

To bude záviset na verzi databáze, kterou používáte, protože optimalizátor je s každým vydáním chytřejší. Používám 11gR1 a optimalizátor použil index ve všech případech kromě jednoho:když byly oba sloupce null a já jsem nezahrnul NOT IN klauzule:

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

Bez klauzule NOT IN...

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>

Když jsem zkopíroval NOT IN klauzule zpět, optimalizátor se rozhodl použít index. Divné.

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>

Jen pro zopakování, ve všech ostatních případech, pokud byl jeden z indexovaných sloupců deklarován jako nenulový, byl k uspokojení dotazu použit index. To nemusí být pravda na dřívějších verzích Oracle, ale pravděpodobně to ukazuje cestu vpřed.



  1. Replikace MySQL:Chybné transakce v replikaci založené na GTID

  2. Jak načíst data mysql pomocí Java multi-threading

  3. Jak uniknout uvozovkám v dotazu MYSQL?

  4. Hluboká aktualizace Oracle SQL