web-dev-qa-db-de.com

Erzwinge Indexverwendung in Oracle

Ich bin auf diese Frage in einem Interview gestoßen und hatte keine Ahnung, wie ich sie beantworten sollte:

Es gibt eine Tabelle mit einem Index für eine Spalte, und Sie fragen Folgendes ab:

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

Die Abfrage dauert zu lange und Sie stellen fest, dass der Index nicht verwendet wird. Wie können Sie die Abfrage zur Verwendung des Index zwingen, wenn Sie der Meinung sind, dass die Leistung der Abfrage mit dem Index besser ist?

32
Vijay

Sie können Optimierungshinweise verwenden

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

Weitere Hinweise zur Verwendung des Optimierers: http://download.Oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref.htm

43
Rene

Es könnte viele Gründe geben, wenn der Index nicht verwendet wird. Auch nachdem Sie Hinweise angeben, gibt es Chancen, dass Oracle Optimizer anders denkt und sich nicht entscheidet Index verwenden. Sie müssen den Teil EXPLAIN PLAN durchgehen und sehen, was die Anweisung mit INDEX und ohne INDEX kostet.

Angenommen, Oracle verwendet CBO . Wenn das Optimierungsprogramm den Eindruck hat, dass die Kosten für INDEX hoch sind, ignoriert es das Optimierungsprogramm in den meisten Fällen und fährt mit dem vollständigen Tabellenscan fort, obwohl Sie dies in Hinweisen angeben. Ihre erste Aktion sollte darin bestehen, DBA_INDEXES zu überprüfen, um festzustellen, wann die Statistiken LAST_ANALYZED sind. Wenn nicht analysiert, können Sie Tabelle, Index für Analyse setzen .

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

Für den Tisch.

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

In extremen Fällen können Sie versuchen Einrichten der Statistik auf eigene Faust.

13
Guru

Wie können Sie die Abfrage zur Verwendung des Index zwingen, wenn Sie der Meinung sind, dass die Leistung der Abfrage mit dem Index besser ist?

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

Der Indexhinweis ist hier der Schlüssel, aber die aktuellere Art der Angabe erfolgt 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"; 

In Bezug auf zusammengesetzte Indizes bin ich nicht sicher, ob Sie alle Spalten angeben müssen , aber es scheint eine gute Idee zu sein. Lesen Sie die Dokumente 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.

12
David Aldridge

Es gibt einen geeigneten Index für column_having_index, und seine Verwendung erhöht tatsächlich die Leistung, aber Oracle hat ihn nicht verwendet ...
Sie sollten Statistiken sammeln für Ihre Tabelle, damit das Optimierungsprogramm erkennt, dass der Indexzugriff hilfreich sein kann. Der direkte Hinweis ist keine gute Praxis.

2
Egor Rogov