2009-12-03 8 views
25

stieß ich auf diese Frage in einem Interview und hatte keine Ahnung, wie zu beantworten:Force-Index Verwendung in Oracle

Es gibt eine Tabelle, die einen Index für eine Spalte hat, und Sie fragen:

select * from table_name where column_having_index="some value"; 

Die Abfrage dauert zu lange und Sie finden heraus, dass der Index nicht verwendet wird. Wenn Sie glauben, dass die Leistung der Abfrage mithilfe des Index besser ist, wie können Sie die Abfrage erzwingen, den Index zu verwenden?

Antwort

37

können Sie verwenden Optimierungshinweise

select /*+ INDEX(table_name index_name) */ from table etc ...

Mehr zur Verwendung von Optimierungshinweise: http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref.htm

+1

Auch in neueren Versionen von Oracle (10g + denke ich) können Sie den Spaltennamen anstelle des Indexnamens angeben, z. '/ * + INDEX (table_name column_having_index) * /' –

+1

/* + INDEX (table_name (column_having_index)) */... siehe meine Antwort für komplexere Syntax –

+1

Korrekte Syntax ist (Sie müssen Tabellenalias verwenden!): Wählen Sie/* + INDEX (xxxTABLExxx index_name) */aus table_name xxxTABLExxx – xnagyg

-4

können Sie verwenden:

WITH index = ... 

more info

+0

ohh .. meinst du meinst MS-Sql ... aber Sie bekommen die Idee :) – Leon

2

Es gibt einen entsprechenden Index für column_having_index, und dessen Verwendung erhöht die Leistung, aber Oracle hat sie nicht verwendet ...
Sie sollten Statistiken auf Ihrer Tabelle sammeln, damit der Optimierer sieht, dass der Indexzugriff helfen kann. Direkter Hinweis ist keine gute Übung.

+1

Indexing Tipps sollten sicherlich sparsam verwendet werden, aber es gibt viele legitime Situationen für ihre Verwendung. Ein Beispiel ist, wo die Statistiken nicht verfügbar sind, um zu demonstrieren, dass Spaltenwerte stark korreliert sind, und der CBO leitet eine falsche Kardinalität für Prädikate für mehrere Spalten ein. –

+1

David, was die Frage angeht, das Beispiel ist so einfach, dass ich keinen Grund sehe, warum CBO den Index nicht für falsche Statistiken verwendet. Aber im Allgemeinen - Sie haben natürlich Recht. –

13

Es könnte sein viele Gründe für Index nicht verwendet werden. Auch nach Ihnen specify hints, gibt es Chancen Oracle Optimizer denkt anders und entscheiden, nicht zu verwenden Index. Sie müssen den Teil EXPLAIN PLAN durchlaufen und sehen, welche Kosten die Anweisung mit INDEX und ohne INDEX verursacht.

Angenommen die Oracle uses CBO. Wenn das Optimierungsprogramm der Ansicht ist, dass die Kosten bei INDEX hoch sind, ignoriert das Optimierungsprogramm den gesamten Tabellenscan, auch wenn Sie es in Hinweisen angeben. Ihre erste Aktion sollte DBA_INDEXES überprüfen, um zu wissen, wann die Statistik LAST_ANALYZED ist. Wenn nicht analysiert, können Sie set table, index for analyze.

begin 
    DBMS_STATS.GATHER_INDEX_STATS (OWNNAME=>user 
           , INDNAME=>IndexName); 
end; 

Für Tabelle.

begin 
    DBMS_STATS.GATHER_TABLE_STATS (OWNNAME=>user 
           , TABNAME=>TableName); 
end; 

In extremen Fällen können Sie setting up the statistics auf eigene Faust versuchen.

+0

Das CBO wird "immer" alle * korrekt spezifizierten * Hinweise beachten - es hat keine Freiheit willkürlich "auszuwählen", um einen Hinweis nicht zu beachten. –

+4

Kürzlich haben wir ORA 9208 von ORA 9205 verbessert, danach haben wir dies erlebt, es gab eine komplexe Abfrage, INDEX wurde nicht verwendet. Ich zwang es mit dem TIPP. Obwohl das EXPLAIN_PLAN-Objekt den INDEX-Code anzeigte, erforderte es bei der Ausführung einen anderen Pfad. Damals hat uns DBA vorgeschlagen, das SQL neu zu schreiben. Und wir haben das gemacht, es hat funktioniert. – Guru

9

Wenn Sie der Meinung sind, dass die Leistung der Abfrage mit dem Index besser ist, wie können Sie die Abfrage erzwingen, den Index zu verwenden?

Zuerst würden Sie natürlich überprüfen, dass der Index ein besseres Ergebnis für die Rückgabe des vollständigen Datensatzes ergab, oder?

Der Indexhinweis ist hier der Schlüssel, aber die aktuellere Art der Angabe ist mit der Spaltenbenennungsmethode und nicht mit der Indexbenennungsmethode. In Ihrem Fall würden Sie verwenden:

select /*+ index(table_name (column_having_index)) */ * 
from table_name 
where column_having_index="some value"; 

In komplexeren Fällen könnten Sie ...

select /*+ index(t (t.column_having_index)) */ * 
from my_owner.table_name t, 
     ... 
where t.column_having_index="some value"; 

Hinsichtlich zusammengesetzten Indizes, ich bin nicht sicher, dass Sie Notwendigkeit alle Spalten zu spezifizieren, aber es scheint wie eine gute Idee. Sehen Sie die Dokumentation hier http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#autoId18 für mehrere index_specs und die Verwendung von index_combine für mehrere Indizes, und hier http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#BABGFHCH für die Angabe mehrerer Spalten in der index_spec.

+0

Wie sieht es aus, wenn der Index mehrere Spalten umfasst? Muss ich alle angeben? – shindigo

+0

Verbesserte die Antwort für mehrere Spalten, @shindigo –

Verwandte Themen