Ho una 10.2.0.3 database Oracle, e una query come questa:Oracle spiegare il piano previsionale delle cardinalità non corretta per una gamma di indice di scansione
select count(a.id)
from LARGE_PARTITIONED_TABLE a
join SMALL_NONPARTITIONED_TABLE b on a.key1 = b.key1 and a.key2 = b.key2
where b.id = 1000
Tabella LARGE_PARTITIONED_TABLE (a) ha circa 5 milioni di righe, ed è partizionato da una colonna non presente nella query. La tabella SMALL_NONPARTITIONED_TABLE (b) non è partizionata e contiene circa 10000 righe.
Le statistiche sono aggiornate e sono presenti istogrammi bilanciati in altezza nelle colonne key1 e key2 della tabella a.
La tabella a ha una chiave primaria e un indice univoco globale non partizionato sulle colonne key1, key2, key3, key4 e key5.
Spiega piano per l'interrogazione visualizza i seguenti risultati:
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 31 | 4 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 31 | | |
| 2 | NESTED LOOPS | | 406 | 12586 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN| INDEX_ON_TABLE_B | 1 | 19 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN| PRIMARY_KEY_INDEX_OF_TABLE_A | 406 | 4872 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("b"."id"=1000)
4 - access("a"."key1"="b"."key1" and
"a"."key2"="b"."key2")
quindi il file (cardinalità) stimato per il passaggio 4 è .
Ora, un TKPROF traccia rivela quanto segue:
Rows Row Source Operation
------- ---------------------------------------------------
1 SORT AGGREGATE (cr=51 pr=9 pw=0 time=74674 us)
7366 NESTED LOOPS (cr=51 pr=9 pw=0 time=824941 us)
1 INDEX RANGE SCAN INDEX_ON_TABLE_B (cr=2 pr=0 pw=0 time=36 us)(object id 111111)
7366 INDEX RANGE SCAN PRIMARY_KEY_INDEX_OF_TABLE_A (cr=49 pr=9 pw=0 time=810173 us)(object id 222222)
Così la cardinalità in realtà era , non 406!
mia domanda è questa: Da dove viene Oracle ottiene la cardinalità stimata di 406 in questo caso, e Come posso migliorare la sua accuratezza, in modo che la stima è più in linea di ciò che accade realmente durante l'esecuzione di query ?
Aggiornamento: Ecco un frammento di una traccia 10053 mi sono imbattuto sulla query.
NL Join
Outer table: Card: 1.00 Cost: 2.00 Resp: 2.00 Degree: 1 Bytes: 19
Inner table: LARGE_PARTITIONED_TABLE Alias: a
...
Access Path: index (IndexOnly)
Index: PRIMARY_KEY_INDEX_OF_TABLE_A
resc_io: 2.00 resc_cpu: 27093
ix_sel: 1.3263e-005 ix_sel_with_filters: 1.3263e-005
NL Join (ordered): Cost: 4.00 Resp: 4.00 Degree: 1
Cost_io: 4.00 Cost_cpu: 41536
Resp_io: 4.00 Resp_cpu: 41536
****** trying bitmap/domain indexes ******
Best NL cost: 4.00
resc: 4.00 resc_io: 4.00 resc_cpu: 41536
resp: 4.00 resp_io: 4.00 resp_cpu: 41536
Using concatenated index cardinality for table SMALL_NONPARTITIONED_TABLE
Revised join sel: 8.2891-e005 = 8.4475e-005 * (1/12064.00) * (1/8.4475e-005)
Join Card: 405.95 = outer (1.00) * inner (4897354.00) * sel (8.2891-e005)
Join Card - Rounded: 406 Computed: 405.95
Ecco da dove viene il valore 406. Come ha risposto Adam, unire la cardinalità è join selectivity * filter cardinality (a) * filter cardinality (b)
, come si può vedere nella penultima frase della penultima traccia.
Quello che non capisco è la linea Revised join sel
. 1/12064 è la selettività dell'indice utilizzato per trovare la riga dalla tabella b (12064 righe sulla tabella e selezionare in base all'ID univoco). Ma allora cosa?
cardinalità sembra essere calcolato moltiplicando cardinalità filtro di tabella b (4.897.354) con selettività tavolo un (1/12064). Perché? Che cosa è la tabella di selettività nella tabella a quanto si deve trovare righe da tabella b, quando un join -> b non è basato su a.id?
Da dove viene il numero 8.4475e-005 provengono da (non appare da nessun'altra parte nell'intera traccia )? Non che ciò influisca sull'output , ma mi piacerebbe comunque saperlo.
Capisco che l'ottimizzatore abbia probabilmente scelto il percorso corretto qui. Ma ancora la cardinalità viene calcolato male - e che può avere un effetto importante sul percorso di esecuzione che viene scelto da quel punto in poi (come nel caso sto avendo IRL - questo esempio è una semplificazione di quello).
Grazie Adam. Darò sicuramente un'occhiata alla traccia 10053 della query. Pubblicherò i miei risultati domani. – Tommi
Ora ho aggiornato la domanda con la traccia 10053, vedere sopra. – Tommi
Non riesco a rispondere alla seconda domanda: Oracle ha molti fattori fondenti e le regole di cardinalità dell'indice concatenate non sono ben documentate. Inoltre, è un fattore che si annulla. Il AB join cardinalità si basa sulla relativa cardinalità di A (1 fila) moltiplicato per la cardinalità assoluta di B (4.897.354) moltiplicato per la selettività join - che è 1/cardinalità assoluto di A. guardare in questo modo. Le tue tabelle associano 12046 righe in A a 4897354 righe in B. Pertanto, per ogni riga in A, ci sono, in media, 406 righe in B. –