Frage

Was sind einige Dinge, die ich tun kann, ohne das Erstellen von Indizes Abfrageleistung eines Orakel Abfrage zu verbessern?

Hier ist die Abfrage Ich versuche, schneller zu laufen:

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath
FROM items a,
itempages b,
keygroupdata c
WHERE a.ItemType IN (112,115,189,241)
AND a.ItemNum = b.ItemNum
AND b.ItemNum = c.ItemNum
ORDER BY a.DateStored DESC

Keine dieser Spalten indiziert sind und jeder der Tabellen enthält Millionen von Datensätzen. Unnötig zu sagen, es dauert mehr als 3 und einhalb Minuten für die Abfrage auszuführen. Dies ist eine Dritte-Datenbank in einer Produktionsumgebung, und ich bin keine Indizes erstellen erlaube so dass alle Leistungsverbesserungen auf die Abfrage gemacht werden müßten selbst.

Danke!

War es hilfreich?

Lösung

Zuerst würde ich die Abfrage neu schreiben ANSI-Standard zu sein:

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath
FROM items a
INNER JOIN itempages b ON b.ItemNum = a.ItemNum
INNER JOIN keygroupdata c ON c.ItemNum = b.ItemNum
WHERE a.ItemType IN (112,115,189,241)
ORDER BY a.DateStored DESC

Das macht es leichter zu lesen und zu verstehen, was los ist. Es hilft Ihnen auch keine Fehler machen (das heißt Kreuz Beitritt), die wirklich große Probleme verursachen könnten. Dann würde ich den Plan erklären, um zu sehen, was das DBMS mit dieser Abfrage tut. Ist es versucht, einige Indizes zu benutzen? Ist es die Tabellen korrekt anzuschließen?

Dann würde ich die Tabellen überprüfen, die ich mit gerade arbeite, um zu sehen, ob es irgendwelche Indizes sind, die bereits existieren, dass ich verwenden könnte, um meine Anfrage schneller zu machen. Schließlich wie alle anderen vorgeschlagen hat ich die Order By-Klausel entfernen würde und genau das tun im Code.

Andere Tipps

Stellen Sie die Dritten zu indizieren ihre Spalten verbinden, da sie in erster Linie getan haben sollte! Ohne Indizes hat Oracle nichts anderes zu gehen, als rohe Gewalt.

Sie möchten vielleicht versuchen, eine materialisierte Ansicht auf eine dieser Tabellen zu erstellen. Anschließend können Sie einen Index für die materialisierte Ansicht erstellen, die die Abfrage beschleunigen helfen (die dann die materialisierte Ansicht werden die Abfrage würde anstelle der rohen Tabelle).

Natürlich, wenn die zugrunde liegende Tabelle aktualisiert wird Ihre Sicht und Indizes müssen aktualisiert werden.

Zuerst schauen Sie sich den Ausführungsplan. Ist es genau die Anzahl der Zeilen beziehen sich auf jeder Stufe der Ausführung der Abfrage abgerufen werden? Wie selektiv ist das Prädikat „a.ItemType IN (112115189241)“? Ist der Plan zeigt Ausführung jegliche Verwendung von temporärer Speicherplatz für beitritt oder Sorten?

Eigentlich, vielleicht können Sie die Frage ändern, um den Ausführungsplan enthalten.

Auch stellen Sie sicher, Sie haben nicht Hash deaktiviert Joins, was manchmal der Fall in OLTP-Systemen abgestimmt ist, da sie die effizienteste Art und Weise von equijoining Massendaten in Oracle sind. Sie sollten in dem Ausführungsplan zeigen.

Sie können versuchen, das Filtern auf Elementtyp, bevor Sie Tabellen verbinden, wie hier gezeigt.

Wenn Sie auf Oracle 9i vor laufen, das manchmal überraschende Vorteile geben würde.

select 
  c.claimnumber,
  a.itemdate, 
  c.dtn,
  b.filepath
from 
  (
  select itemdate
  from items it
  where it.itemtype in(112,115,189,241)
  ) a
  itempages b,
  keygroupdata c
where a.itemnum = b.itemnum
  and b.itemnum = c.itemnum

Sie auch die Hinweise können versuchen, das Hinzufügen / + RULE / oder / + BESTELLT /, um zu sehen, was passiert ... wieder, vor allem mit älteren Versionen, diese würden manchmal gibt überraschende Ergebnisse.

SELECT /*+RULE*/
  c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath
FROM
  items a,
  itempages b,
  keygroupdata c
WHERE a.ItemType IN (112,115,189,241)
  AND a.ItemNum = b.ItemNum
  AND b.ItemNum = c.ItemNum
ORDER BY a.DateStored DESC

Wenn die Abfrageeingänge sind konstant oder vorhersagbar (die itemType IN (...)), dann wäre eine Alternative die Abfrage ein- oder zweimal am Tag laufen und die Ergebnisse in einer lokalen Tabelle zu speichern, mit Indizes gegebenenfalls.

Sie können dann die teure Abfrage ‚offline‘ machen und haben schneller / bessere Ergebnisse für eine interaktive Abfrage.

Ist das eine Abfrage, die Sie oft laufen? Es scheint, wie es in der DB Eigentümer Interesse sein würde, die Indizes zu erstellen, die Sie diese Abfrage beschleunigen müssen. Die 3,5 Minuten Sie verbringen die Abfrage ausgeführt wird, muss einen gewissen Einfluss auf ihre Produktionsumgebung haben!

Außerdem haben sie neue Statistiken über die Tabellen laufen? Das könnte die Leistung verbessern, da die Verknüpfungsreihenfolge auf der Grundlage der Statistik der Tabellen berechnet wird.

BTW, was Sie tun dürfen? Gerade gelesen? Wenn Sie temporäre Tabellen erstellen und setzen Indizes für diejenigen, ich könnte prüfen, temporäre Kopien der Tabelle machen, Indizieren diejenigen, und führen Sie dann den Index-unterstützte sich mit den temporären Kopien.

Ich weiß, dass dieses Thema ist sehr alt, aber für die Suchmaschinen Ich wollte noch eine alternative Lösung bieten, die auf Oracle arbeiten und auf den Daten abhängig könnte viel schneller sein.

with a as (
  select 
    * 
  from 
    items 
  where 
    ItemType IN (112,115,189,241)
)
SELECT 
  c.ClaimNumber
  , a.ItemDate
  , c.DTN, b.FilePath
FROM 
  a,
  itempages b,
  keygroupdata c
WHERE 
  a.ItemNum = b.ItemNum
  AND b.ItemNum = c.ItemNum
ORDER BY 
  a.DateStored DESC

Sie können auch den /*+ MATERIALIZE */ Hinweis in der WITH Klausel versuchen.

Eigentlich finde ich Orakel alte Join-Syntax viel einfacher als ANSI SQL-lesen ^^

Ohne Indizierung, die Abfrage wird nur als Tabellengröße zunimmt, schlechter zu erhalten. Mit diesem wird gesagt, versuchen Sie die ORDER BY-Klausel zu entfernen und diese Art auf der Client-Seite tun.

Manchmal kann man einen Vorteil durch das Hinzufügen von zusätzlichen Bahnen für den Optimierer sehen wählen durch Hinzufügen was wie redundante Elemente der scheint where-Klausel.

Zum Beispiel, Sie haben A.ItemNum = B.ItemNum UND B.ItemNum = C.ItemNum. Versuchen Sie A.ItemNum = C.ItemNum auch hinzufügen. Ich bin mir ziemlich sicher aber, dass der Optimierer intelligent genug ist, dass auf seinem eigenen, um herauszufinden - wenn auch einen Versuch wert

.

Je nach Datentyp der ItemType Spalte, die Sie schneller auftreten können Ausführung die Verwendung von folgenden, wenn es ein varchar ist, wird Oracle implict Konvertierungen.

SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath
FROM items a,
itempages b,
keygroupdata c
WHERE ((a.ItemType IN ('112','115','189','241'))
AND (a.ItemNum = b.ItemNum)
AND (b.ItemNum = c.ItemNum))
ORDER BY a.DateStored DESC

Statistiken über diese Tabellen gesammelt? Wenn nicht, Statistiken zu sammeln könnte den Ausführungsplan ändern, auch wenn es nicht unbedingt zum Besseren sein würde.

Abgesehen davon, Blick auf den Ausführungsplan. Sie können sehen, dass es die Tabellen in einer nicht-optimalen Reihenfolge beitritt (z könnte es b und c beitreten, bevor sie mit einem Beitritt, die die Filterbedingung hat).

Sie könnten Hinweise verwenden, um zu versuchen, die Zugriffspfade zu beeinflussen, an der Reihenfolge, oder Verfahren beizutreten.

Aktualisieren : zum Kommentar Als Reaktion führte mich zu dieser Präsentation, die hilfreich sein könnte oder zumindest interessant.

Wenn Sie sagen, dass es keine Indizes sind, dann bedeutet das auch, dass es keine Primär- oder Fremdschlüssel definiert? Offensichtlich Analyse der Tabellen und das Sammeln von Statistiken sind wichtig, aber wenn Metadaten wie definiert, wie die Tabellen sollen verbunden werden nicht existiert, dann Oracle kann auch einen schlechten Ausführungspfad wählen.

In diesem Fall einen Hinweis verwendet wie / * + * BESTELLT / gut die einzige Option sein, um wählen Sie den Optimierer zuverlässig einen guten Ausführungspfad. Es kann auch noch hinzugefügt, Fremdschlüssel und Primärschlüssel sein, aber sie als DISABLE und VALIDATE definieren.

Ich denke, die Nützlichkeit dieser Kommentar hängt davon ab, wie weit die Abneigung gegen Indizes geht so YMMV.

Zuerst eine Sicht auf dieser Abfrage erstellen und dann eine Tabelle aus dieser Ansicht erzeugen. Auch einen Index für Datum zu erstellen, einen Job machen und es in Mitternacht Zeit einplanen, wenn das System im Leerlauf ist.

Nun, da Sie nicht Indizes erstellen können, würde ich sicherstellen, dass die Statistiken alle up-to-date sind dann, ich die Abfrage so umschreiben würde:

with a as (select /*+ MATERIALIZE */ ItemType, ItemNum, DateStored, ItemDate from items where ItemType in (112,115,189,241)) SELECT c.ClaimNumber, a.ItemDate, c.DTN, b.FilePath FROM a, itempages b, keygroupdata c WHERE a.ItemNum = b.ItemNum AND b.ItemNum = c.ItemNum ORDER BY a.DateStored DESC

Nehmen Sie die ORDER BY

führen Sie die Art, nachdem Sie die Zeilen zurück in Ihre Anwendung ziehen.

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