Ich habe eine Tabelle mit 250 KB Zeilen in meiner Testdatenbank. (Es werden ein paar Hundert Millionen produziert, wir können dort dasselbe Problem beobachten.) Die Tabelle hat eine Zeichenfolgen-ID nvarchar2 (50), die nicht null ist und einen eindeutigen Index enthält (es ist nicht die PK).
Die Bezeichner bestehen aus einem ersten Teil mit 8 verschiedenen Werten in meiner Testdatenbank (und ungefähr tausend in der Produktion), einem @ -Zeichen und schließlich einer 1- bis 6-stelligen Zahl. Zum Beispiel könnte es 50.000 Zeilen geben, die mit 'ABCD_BGX1741F_2006_13_20110808.xml @' beginnen, gefolgt von 50.000 verschiedenen Zahlen.
Wenn ich eine einzelne Zeile basierend auf ihrem Bezeichner abfrage, wird die Kardinalität auf 1 geschätzt, die Kosten sind sehr gering und es funktioniert einwandfrei. Wenn ich mehr als eine Zeile mit mehreren Bezeichnern in einem IN-Ausdruck oder einem OR-Ausdruck abfrage, sind die Schätzungen für den Index völlig falsch, sodass ein vollständiger Tabellenscan verwendet wird. Wenn ich den Index mit einem Hinweis erzwinge, ist er sehr schnell, der vollständige Tabellenscan wird tatsächlich eine Größenordnung langsamer ausgeführt (und viel langsamer in der Produktion). Es ist also ein Optimierungsproblem.
Als Test habe ich die Tabelle (im selben Schema + Tablespace) mit genau derselben DDL und genau demselben Inhalt dupliziert. Ich habe den eindeutigen Index für die erste Tabelle aus gutem Grund neu erstellt und genau denselben Index für die Klontabelle erstellt. Ich habe eine DBMS_STATS.GATHER_SCHEMA_STATS('schemaname',estimate_percent=>100,cascade=>true);
. Sie können sogar sehen, dass die Indexnamen fortlaufend sind. Der einzige Unterschied zwischen den beiden Tabellen besteht nun darin, dass die erste über einen langen Zeitraum in zufälliger Reihenfolge geladen wurde, wobei Blöcke auf der Festplatte verteilt waren (in einem Tablespace zusammen mit mehreren anderen großen Tabellen). Die zweite Tabelle wurde als Stapel geladen INSERT-SELECT. Ansonsten kann ich mir keinen Unterschied vorstellen. (Die Originaltabelle wurde seit der letzten großen Löschung verkleinert, und danach gab es keine einzige Löschung mehr.)
Hier sind die Abfragepläne für die Kranken- und die Klontabelle (Die Zeichenfolgen unter dem schwarzen Pinsel sind auf dem gesamten Bild und auch unter dem grauen Pinsel gleich.):
(In diesem Beispiel gibt es 1867-Zeilen, die mit dem schwarz gepinselten Bezeichner beginnen. Eine 2-zeilige Abfrage ergibt eine Kardinalität von 1867 * 2, eine 3-zeilige Abfrage ergibt eine Kardinalität von 1867 * 3 usw.) Zufall, Oracle scheint sich nicht um das Ende der Bezeichner zu kümmern.)
Was könnte dieses Verhalten verursachen? Offensichtlich wäre es ziemlich teuer, die Tabelle in der Produktion neu zu erstellen.
USER_TABLES: http://i.stack.imgur.com/nDWze.jpg USER_INDEXES: http://i.stack.imgur.com/DG9um.jpg Ich habe nur den Namen des Schemas und des Tabellenbereichs geändert. Sie können sehen, dass die Tabellen- und Indexnamen mit denen auf dem Bildschirmfoto des Abfrageplans übereinstimmen.