Tengo una base de datos Oracle 10.2.0.3, y una consulta como esta:Oracle explicar el plan estimaciones de cardinalidad incorrecto para un rango de exploración de índice
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
Tabla LARGE_PARTITIONED_TABLE (a) tiene unos 5 millones de filas, y se reparte por una columna no presente en la consulta. La tabla SMALL_NONPARTITIONED_TABLE (b) no está particionada y contiene aproximadamente 10000 filas.
Las estadísticas están actualizadas, y hay histogramas de altura equilibrada en las columnas clave1 y clave2 de la tabla a.
La tabla a tiene una clave principal y un índice único global sin particiones en las columnas clave1, clave2, clave3, clave4 y clave5.
explicar el plan para la consulta mostrará los siguientes resultados:
---------------------------------------------------------------------------------------------------
| 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")
lo tanto las filas (cardinalidad) estimado para el paso 4 es .
Ahora, un rastro TKPROF revela lo siguiente:
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)
Así que la cardinalidad en la realidad era , no 406!
Mi pregunta es la siguiente: De dónde Oracle conseguir la cardinalidad estimado de 406 en este caso, y ¿Cómo puedo mejorar la precisión de, por lo que la estimación es más en la línea de lo que realmente sucede durante la ejecución de la consulta ?
Actualización: Aquí hay un fragmento de una traza 10053 me encontré en la consulta.
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
Así que de ahí viene el valor 406. Al igual que Adam respondió, unir cardinalidad es join selectivity * filter cardinality (a) * filter cardinality (b)
, como se puede ver en la penúltima línea de la cita de seguimiento anterior.
Lo que no entiendo es la línea Revised join sel
. 1/12064 es la selectividad del índice utilizado para encontrar la fila de la tabla b (12064 filas en la tabla, y seleccionar en base a una identificación única). ¿Y qué?
Cardinalidad parece ser calculado por multiplicando la cardinalidad filtro de la Tabla B (4.897.354) con selectividad de la tabla A (1/12064). ¿Por qué? ¿Qué tiene la selectividad en la tabla tiene que ver con la cantidad de filas se espera que se encuentre en tabla b, cuando a -> b unirse no se basa en a.id?
Dónde se encuentra el número 8.4475e-005 vienen (no aparece en ningún otro lado en el rastro )? No es que afecte a la salida , pero aún me gustaría saberlo.
Entiendo que es probable que el optimizador haya elegido la ruta correcta aquí. Pero aún así el cardinalidad es calculado mal - y que puede tener un efecto importante en la ruta de ejecución que se elige a partir de ese punto en adelante (como en el caso que estoy teniendo IRL - este ejemplo es una simplificación de eso).
Gracias Adam. Ciertamente echaré un vistazo al rastro 10053 de la consulta. Publicaré mis resultados mañana. – Tommi
He actualizado la pregunta con la traza 10053, por favor vea arriba. – Tommi
No puedo responder a la segunda pregunta: Oracle tiene muchos factores falsificados, y las reglas de cardinalidad del índice concatenados no están bien documentadas. Además, es un factor que se anula. La cardinalidad de unión AB se basa en la cardinalidad relativa de A (1 fila) multiplicada por la cardinalidad absoluta de B (4897354) multiplicada por la selectividad de unión - que es 1/cardinalidad absoluta de A. Míralo esto camino. Sus tablas asignan 12046 filas en A a 4897354 filas en B. Por lo tanto, para cada fila en A, hay, en promedio, 406 filas en B. –