Frage

Ich habe diese Tabelle:

create table demo (
    key number(10) not null,
    type varchar2(3) not null,
    state varchar2(16) not null,
    ... lots more columns ...
)

und dieser Index:

create index demo_x04 on demo(key, type, state);

Wenn ich diese Abfrage ausführe

select * from demo where key = 1 and type = '003' and state = 'NEW'

EXPLAIN PLAN zeigt, dass es einen vollständigen Tischscan ausführt. Also habe ich den Index fallen gelassen und ihn erneut erstellt. EXPLAIN PLAN Sagt immer noch Volltisch -Scan. Wie kann das sein?

Einige Hintergrundinformationen: Dies sind historische Daten. Was passiert also, dass ich mit dem Zustand eine Reihe nach oben schaue CLEARED und fügen Sie eine neue Reihe mit Zustand ein NEW (Plus kopiere ich ein paar Werte aus der alten Zeile). Die alte Zeile wird dann aktualisiert auf USED. Also wächst der Tisch immer. Was ich bemerkt habe, ist, dass die Kardinalität des Index 0 beträgt (trotz der Tatsache, dass ich Tausende verschiedener Werte habe). Nach der Nachbildung wuchs die Kardinalität, aber der CBO gefiel den Index nicht besser.

Am nächsten Morgen mochte Oracle plötzlich den Index (wahrscheinlich schlief darüber) und begann ihn zu benutzen, aber nicht lange. Nach einer Weile fiel die Verarbeitung von 50 Zeilen/s auf 3 Zeilen/s und ich sah erneut "Volltisch -Scan". Was ist los?

In meinem Fall muss ich ungefähr eine Million Zeilen verarbeiten. Ich beende die Änderungen in Chargen von ca. 50. Gibt es einen Befehl, den ich nach dem Aufwand ausführen sollte, den Index zu aktualisieren/neu zu formulieren oder so ähnlich?

Ich bin auf Oracle 10g.

Bearbeiten] Ich habe 969'491 verschiedene Schlüssel in dieser Tabelle, 3 Typen und 3 Zustände.

War es hilfreich?

Lösung

Was passiert, wenn Sie einen Index -Hinweis angeben? Versuche dies:

SELECT /*+ INDEX (demo demo_x04) */ * 
  FROM demo 
 WHERE key = 1 
   AND type = '003' 
   AND state = 'NEW';

Es hört sich so an, als ob über Nacht der Tisch analysiert wurde. Als Sie Ihre Verarbeitung gegen die Tabelle durchführten, wurde genügend des Index aktualisiert, um die Statistiken von Oracle -Tabelle erneut abzuschließen, und der Optimierer hat die Verwendung des Index eingestellt.

Fügen Sie den Hinweis hinzu und prüfen Sie, ob Erklärungsplan Ihnen einen anderen Plan bietet und die Abfrage besser funktioniert.

Oh, und Tonys Antwort auf die Analyse der Tabelle ist eine allgemeine gute Praxis, obwohl die Datenbank mit 10G in dieser Hinsicht ziemlich gut darin ist, selbstwart zu sein. Wenn Ihr Prozess viele Aktualisierungen durchführt, kann der Index schnell veraltet werden. Wenn das Ausführen von Analyse, wenn Ihr Prozess im Graben beginnt, die Situation für eine Weile verbessert, dann wissen Sie, dass dies das Problem ist.

Verwenden Sie die Statistiken für die Tabelle, um die Tabelle zu aktualisieren DMBS_Stats.gather_table_stats Paket.

Zum Beispiel:

Exec dbms_stats.gather_table_stats ('der Eigentümer', 'Demo');

Andere Tipps

Wurde die Tabelle in letzter Zeit analysiert? Wenn Oracle der Meinung ist, dass es sehr klein ist, kann es nicht einmal in Betracht ziehen, den Index zu verwenden.

Versuche dies:

select last_analyzed, num_rows 
from user_tables
where table_name = 'DEMO';

Num_rows sagt Ihnen, wie viele Zeilen Oracle denkt, die Tabelle enthält.

"Am nächsten Morgen mochte Oracle plötzlich den Index (wahrscheinlich schlief darüber)" wahrscheinlich läuft ein dbms_stats über Nacht.

Im Allgemeinen würde ich einen von drei Gründen für einen vollständigen Tabellen -Scan über einen Index sehen. Das erste ist, dass der Optimierer der Meinung ist, dass der Tisch leer oder zumindest sehr klein ist. Ich vermute, das war das ursprüngliche Problem. In diesem Fall wäre es schneller, eine Tabelle zu scannen, die nur aus einer Handvoll Blöcken besteht, anstatt einen Index zu verwenden.

Der zweite ist, wenn die Abfrage so ist, dass ein Index praktisch nicht verwendet werden kann.

"select * from demo where key = 1 and type = '003' and state = 'NEW'"

Verwenden Sie tatsächlich Literale, die in der Abfrage fest codiert sind? Wenn nicht, sind Ihre variablen Datentypen möglicherweise falsch (z. B. Zeichen ist Zeichen). Dies würde erfordern, dass der numerische Schlüssel zum Vergleich in das Zeichen konvertiert wird, was den Index nahezu nutzlos machen würde.

Der dritte Grund ist, wo der Ansicht, dass die Abfrage einen großen Teil der Zeilen in der Tabelle verarbeitet. Typ und Zustand scheinen ziemlich niedrig zu kardinalität. Haben Sie vielleicht eine große Anzahl eines bestimmten "Schlüssel"?

Ein Kommentar zu der Verarbeitung, die Sie beschreiben: Es hört sich so an, als würden Sie eine Reihe von Reihen mit zeitweiligen Commits durchführen, und ich würde Sie dringend bitten, dies zu überdenken, wenn Sie können. Der Aktualisierungs-/Einfügemechanismus kann durchaus in eine Merge -Anweisung konvertiert werden und der gesamte Datensatz kann dann in einer einzigen Anweisung mit einem Commit am Ende verarbeitet werden. Dies wäre mit ziemlicher Sicherheit schneller und weniger Ressourcen als Ihre aktuelle Methode.

Ist der Wert des Spaltenschlüssels immer 1? In diesem Fall bin ich mir nicht sicher, ob die Beratung des Index die Abfrage optimieren würde, da jede Zeile ohnehin untersucht werden müsste. Wenn ja, deklarieren Sie den Index ohne die Schlüsselspalte. Sie können es auch versuchen:

select key, type, state from demo where key = 1 and type = '003' and state = 'NEW'

Was (wenn meine Vermutung stimmt) müsste immer noch jede Zeile betrachten, aber welches könnte zum Index gehen, da alle Spalten im Ergebnissatz jetzt abgedeckt sind.

Ich rate nur anhand Ihrer Aussage, dass der Index Cardinality 0 zeigt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top