- der traditionelle FIRST_ROWS-Hint ("first_rows is avaiable only for backwards compatibility") hat offenbar keinen Einfluß auf die Cost-Berechnung
- im Fall von FIRST_ROWS(n) scheint in etwa folgende harmlose Formel zu gelten:
Hinweis: wie Randolf Geist in seinem Kommentar erwähnt - und in seiner unten verlinkten Präsentation näher erläutert - ist dieser einfache "proration factor" (= n / total_number_of_rows) nur ein Element innerhalb eines deutlich komplexeren Kalküls.(n/number_of_rows_in_table) * initial_cost
Dazu noch der Test, auf dem meine Annahmen basieren:
create table test_first_rows_hint as select rownum id from dual connect by level <= 1000000; exec dbms_stats.gather_table_stats(user, 'TEST_FIRST_ROWS_HINT', estimate_percent => 100) select * from test_first_rows_hint; 1000000 Zeilen ausgewählt. Abgelaufen: 00:00:03.96 Ausführungsplan ---------------------------------------------------------- Plan hash value: 3818872010 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1000K| 4882K| 780 (0)| 00:00:04 | | 1 | TABLE ACCESS FULL| TEST_FIRST_ROWS_HINT | 1000K| 4882K| 780 (0)| 00:00:04 | ------------------------------------------------------------------------------------------
In den folgenden Testläufen wurde die Query dann jeweils mit einem Hint versehen:
- first_rows: 780 (wie im Fall ohne Hint)
- first_rows(1): 2
- first_rows(1000): 3
- first_rows(10000): 9
- first_rows(100000): 80 (ca. 10% der ursprünglichen Kosten bei Optimierung für 10% der Sätze)
- first_rows(500000): 391 (ca. 50% der ursprünglichen Kosten bei Optimierung für 50% der Sätze)
- http://hoopercharles.wordpress.com/2011/03/10/what-is-the-difference-between-the-first_rows-hint-and-rownum-in-the-where-clause/
- http://jonathanlewis.wordpress.com/2008/11/11/first_rows_n/
Hallo Martin,
AntwortenLöschendas mit der "harmlosen" Formel stimmt zwar für diesen trivialen Fall, aber schon für leicht komplexere Abfrage leider nicht mehr, zum Beispiel wenn Indizes mit ins Spiel kommen.
Ich habe mal eine Präsentation über den FIRST_ROWS(n)-Modus gehalten in der Vergangenheit, und konnte keine endgültige Formel finden, die die unterschiedlichen Ergebnisse beschreiben würde. Man findet Links zu der Präsentation und einer erweiterten Version mit Erklärungen hier:
http://oracle-randolf.blogspot.com/2009/12/ukoug-2009-slides.html
Randolf
Hallo Randolf,
AntwortenLöschenDanke für die Hinweise. Die Präsentation ist beeindruckend. Mich erschüttert immer wieder, wie komplex selbst die kleinsten Details werden, wenn man genau genug hinschaut - wobei das vermutlich nicht nur für den CBO gilt...