select /*+ full(t) */ count(*) from dim_table t where t.col1 = 421220 AND t.col2 = 20 COUNT(*) ---------- 2841 ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT REMOTE| | 1 | 9 | 60397 (1)| | 1 | SORT AGGREGATE | | 1 | 9 | | |* 2 | TABLE ACCESS FULL | DIM_TABLE | 147 | 1323 | 60397 (1)| ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("A1"."COL1"=421220 AND "A1"."COL2"=20) Note ----- - fully remote statement
Für das "fully remote statement" erwartet der CBO demnach 147 Sätze, was zwar von den tatsächlichen 2841 rows recht weit entfernt ist, aber immerhin mehr als die 1 (oder 2), die hier ohne die extended statistics erschien.
Für die komplexeren Queries der Applikation blieb es aber trotzdem bei einer deutlichen Unterschätzung der Cardinality für den Zugriff auf DIM_TABLE. Dazu hier ein minimales Beispiel:
select count(*) from fact_table f , dim_table d where f.col0 = d.col0 and d.col1 = 421220 AND d.col2 = 20 and f.col3 = '01.12.2011' COUNT(*) ---------- 13562 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 54 | 8 (0)| | 1 | SORT AGGREGATE | | 1 | 54 | | | 2 | NESTED LOOPS | | 24 | 1296 | 8 (0)| | 3 | REMOTE | DIM_TABLE | 2 | 78 | 4 (0)| | 4 | PARTITION RANGE SINGLE| | 12 | 180 | 2 (0)| |* 5 | INDEX RANGE SCAN | IDX_FACT_TABLE | 12 | 180 | 2 (0)| ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - access("F"."COL0"="A"."COL0" AND "F"."COL3"=TO_DATE(' 2011-12-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')) Remote SQL Information (identified by operation id): ---------------------------------------------------- 3 - SELECT "COL0","COL1","COL2" FROM "DIM_TABLE" "A" WHERE "COL1"=421220 AND "COL2"=20 (accessing 'DBL_XXX' )
Statt der Cardinality-Schätzung 147, die sich bei der einzelnen Ausführung des Remote SQL ergibt, erscheint hier eine 2, was im gegebenen Fall wahrscheinlich kein Problem ist, da der NL hier angemessen erscheint - aber manchmal einen geeigneteren HASH JOIN verhindern könnte. Meine Vermutung ist, dass die Extended Statistics nur beim "fully remote statement" herangezogen werden können, während das Join-Statement auf die Statistiken der Einzelspalten zurückgreift - möglicherweise, weil es in Datenbank A ausgeführt wird, also in 10.2.0.4, wo extended statistics noch gar nicht bekannt sind. Zur Prüfung dieser Annahme ein Versuch mit Ausführung in Datenbank B - erzwungen durch den DRIVING_SITE-Hint, zu dem Jonathan Lewis gelegentlich ein paar Hinweise gegeben hat.
select /*+ DRIVING_SITE(a) */ count(*) from fact_table f , dim_table d where f.col0 = d.col0 and d.col1 = 421220 AND d.col2 = 20 and f.col3 = '01.12.2011' --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT REMOTE | | 1 | 38 | 395 (1)| | 1 | SORT AGGREGATE | | 1 | 38 | | | 2 | NESTED LOOPS | | 1703 | 64714 | 395 (1)| | 3 | TABLE ACCESS BY INDEX ROWID| DIM_TABLE | 147 | 2352 | 100 (0)| |* 4 | INDEX RANGE SCAN | IDX_DIM_TABLE | 147 | | 3 (0)| | 5 | REMOTE | FACT_TABLE | 12 | 264 | 2 (0)| --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("A1"."COL2"=20 AND "A1"."COL1"=421220) Remote SQL Information (identified by operation id): ---------------------------------------------------- 5 - SELECT "COL0","COL3" FROM "XXX"."FACT_TABLE" "A2" WHERE "COL3"=TO_DATE(' 2011-12-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "COL0"=:1 (accessing '!' )
Damit ist man dann wieder bei der 147, was meine Vermutung zu bestätigen scheint. Und damit ist das Problem in diesem Fall vermutlich nicht einmal durch einen Umzug der DIM_TABLE in Datenbank A lösbar, sondern erfordert eine grundsätzlichere Behandlung (oder einen kompletten Umzug der Applikation nach B).
Keine Kommentare:
Kommentar veröffentlichen