Oracle använder inte indexet eftersom det antar select column_value from table(x)
returnerar 8168 rader.
Index är snabbare för att hämta små mängder data. Vid något tillfälle är det snabbare att skanna hela tabellen än att gå igenom indexträdet upprepade gånger.
Att uppskatta kardinaliteten hos en vanlig SQL-sats är svårt nog. Att skapa en korrekt uppskattning för procedurkod är nästan omöjligt. Men jag vet inte var de kom på 8168. Tabellfunktioner används normalt med pipeline-funktioner i datalager, ett ganska stort antal är vettigt.
Dynamisk sampling kan generera en mer exakt uppskattning och sannolikt generera en plan som kommer att använda indexet.
Här är ett exempel på en dålig kardinalitetsuppskattning:
create or replace type type_table_of_number as table of number;
explain plan for
select * from table(type_table_of_number(1,2,3,4,5,6,7));
select * from table(dbms_xplan.display(format => '-cost -bytes'));
Plan hash value: 1748000095
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Time |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8168 | 00:00:01 |
| 1 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | 8168 | 00:00:01 |
-------------------------------------------------------------------------
Så här fixar du det:
explain plan for select /*+ dynamic_sampling(2) */ *
from table(type_table_of_number(1,2,3,4,5,6,7));
select * from table(dbms_xplan.display(format => '-cost -bytes'));
Plan hash value: 1748000095
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Time |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 7 | 00:00:01 |
| 1 | COLLECTION ITERATOR CONSTRUCTOR FETCH| | 7 | 00:00:01 |
-------------------------------------------------------------------------
Note
-----
- dynamic statistics used: dynamic sampling (level=2)