Oracle nie używa indeksu, ponieważ zakłada select column_value from table(x)
zwraca 8168 wierszy.
Indeksy są szybsze przy pobieraniu niewielkich ilości danych. W pewnym momencie szybsze jest przeskanowanie całej tabeli niż wielokrotne chodzenie po drzewie indeksów.
Oszacowanie liczności zwykłej instrukcji SQL jest wystarczająco trudne. Stworzenie dokładnego oszacowania kodu proceduralnego jest prawie niemożliwe. Ale nie wiem, skąd wymyślili 8168. Funkcje tabelowe są zwykle używane z funkcjami potokowymi w hurtowniach danych, duża liczba ma sens.
Dynamiczne próbkowanie może wygenerować dokładniejsze oszacowanie i prawdopodobnie wygenerować plan, który będzie korzystał z indeksu.
Oto przykład złego oszacowania kardynalności:
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 |
-------------------------------------------------------------------------
Oto jak to naprawić:
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)