Why isn't index used for this query?

后端 未结 4 2073
太阳男子
太阳男子 2021-02-05 18:05

I had a query where an index was not used when I thought it could be, so I reproduced it out of curiosity:

Create a test_table with 1.000.000 rows (10 disti

4条回答
  •  不知归路
    2021-02-05 18:45

    I ran Peter's original stuff and reproduced his results. I then applied dcp's suggestion...

    SQL> alter table test_table modify col not null;
    
    Table altered.
    
    SQL> EXEC dbms_stats.gather_table_stats( user, 'TEST_TABLE' , cascade=>true)
    
    PL/SQL procedure successfully completed.
    
    SQL> EXPLAIN PLAN FOR
      2    SELECT col, COUNT(*)
      3    FROM test_table
      4    GROUP BY col;
    
    Explained.
    
    SQL> select * from table(dbms_xplan.display)
      2  /
    
    PLAN_TABLE_OUTPUT
    ------------------------------------------------------------------------------------
    Plan hash value: 2099921975
    
    ------------------------------------------------------------------------------------
    | Id  | Operation             | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |            |    10 |    30 |   574   (9)| 00:00:07 |
    |   1 |  HASH GROUP BY        |            |    10 |    30 |   574   (9)| 00:00:07 |
    |   2 |   INDEX FAST FULL SCAN| TEST_INDEX |  1000K|  2929K|   532   (2)| 00:00:07 |
    ------------------------------------------------------------------------------------
    
    9 rows selected.
    
    SQL>
    

    The reason this matters, is because NULL values are not included in a normal B-TREE index, but the GROUP BY has to include NULL as a grouping "value" in your query. By telling the optimizer that there are no NULLs in col it is free to use the much more efficient index (I was getting an elapsed time of almost 3.55 seconds with the FTS). This is a classic example of how metadata can influence the optimizer.

    Incidentally, this is obviously a 10g or 11g database, because it uses the HASH GROUP BY algorithm, instead of the older SORT (GROUP BY) algorithm.

提交回复
热议问题