Frage

Ich bin mit einer SQL-Abfrage, die die folgenden Form ähnelt:

SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
AND table1.period = table2.period

Und es ist entweder viel zu langsam oder Deadlocks etwas ist, weil es mindestens 4 Minuten dauert zurückzukehren. Wenn ich es, dies zu ändern:

SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
WHERE table1.period = table2.period

dann funktioniert es gut (wenn auch nicht die richtige Anzahl von Spalten zurückkehren). Gibt es eine Möglichkeit, dies zu beschleunigen?

UPDATE : Es tut die gleiche Sache, wenn ich die letzten beiden Zeilen der letzteren Abfrage wechseln:

SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.period = table2.period
WHERE table1.person_uid = table2.person_uid

UPDATE 2: Diese sind eigentlich sieht, dass ich beitreten. Leider sind sie in einer Datenbank Ich habe keine Kontrolle über, so kann ich nicht (leicht) an die Indizierung Änderungen vornehmen. Ich bin geneigt, dem zuzustimmen, dass dies eine obwohl Indizierung Problem. Ich werde ein wenig warten, bevor eine Antwort für den Fall der Annahme, dass eine magische Art und Weise ist diese Abfrage zu stimmen, die ich nicht kenne. Ansonsten werde ich eine der aktuellen Antworten akzeptieren und versuchen, einen anderen Weg, um herauszufinden, zu tun, was ich tun will. Vielen Dank für die Hilfe der jeder so weit.

War es hilfreich?

Lösung

Beachten Sie, dass Aussagen 2 und 3 zum ersten unterschiedlich sind.

Wie? Nun, Sie tun, eine linke äußere Verknüpfung und WHERE-Klausel nicht, dass unter Berücksichtigung der (wie die ON-Klausel der Fall ist). Zumindest versuchen:

SELECT col1, col2
FROM table1, table2
WHERE table1.person_uid = table2.person_uid (+)
AND table1.period = table2.period (+)

und sehen Sie, wenn Sie die gleiche Leistung Ausgabe erhalten.

Welche Indizes haben Sie auf diese Tabellen? Ist diese Beziehung durch einen Fremdschlüssel definiert?

Was Sie wahrscheinlich brauchen, ist ein Composite-Index sowohl auf person_uid und Zeit (auf beiden Tabellen).

Andere Tipps

Ich glaube, Sie müssen verstehen, warum die letzten beide nicht die gleiche Abfrage wie die ersten sind. Wenn Sie ein linkes treten und fügen Sie dann ein where-Klausel ein Feld in der Tabelle auf der rechten Seite des Join referncing (die, die nicht immer einen Datensatz können die erste Tabelle entsprechen), dann haben Sie effektiv die Verbindung geändert eine innere Verknüpfung. Es gibt eine Ausnahme von dieser Regel und das ist, wenn Sie so etwas wie

Referenz
SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
WHERE table2.person_uid is null

In diesem Fall fragen Sie für die Aufzeichnung, die keinen Datensatz in der zweiten Tabelle hat. Aber anders als dieser spezielle Fall, Sie ändern die links zu einem inneren Join, wenn Sie ein Feld in table2 in dem where-Klausel refence.

Wenn die Abfrage nicht schnell genug ist, ich an Ihrer Indizierung aussehen würde.

Alles, was jemand sagen Sie auf der Grundlage der Informationen, die Sie ist eine Vermutung zur Verfügung gestellt.

Schauen Sie sich den Ausführungsplan für die Abfrage. Wenn Sie keinen Grund für die Langsamkeit in dem Plan sehen, die den Plan hier posten.

http://download.oracle .com / docs / cd / B28359_01 / server.111 / b28274 / ex_plan.htm # PFGRF009

Haben Sie Indizes für person_uid und period für beide Tabellen zu den Themen?

Wenn nicht, fügen Sie sie und versuchen Sie es erneut.

Werfen Sie einen Blick auf dem Ausführungsplan und sieht, was die Abfrage tatsächlich tut.

Außerdem: Was sind die Datentypen der Felder? Sind sie gleich in beiden Tabellen? Eine implizite Umwandlung kann wirklich langsam Dinge nach unten.

Haben diese Tabellen Indizes für die Spalten Sie verbinden? Installieren von Oracle kostenlos sqldeveloper Produkt und verwenden Sie es eine „erklären“ auf dieser Abfrage zu tun und sehen, ob es sequenzielle Scans beiden Tabellen tut.

In einer linken verbinden Sie tabelle1 für jede einzelne Kombination des Abtastens werden würde (person_uid, Zeit), dann table2 für alle entsprechenden Datensätze dort zu suchen. Wenn table2 keinen geeigneten Index haben, kann dies auch das Scannen des gesamten dieser Tabelle betreffen.

Meine beste Vermutung, ohne einen Ausführungsplan zu sehen, ist, dass die erste Abfrage (die einzigen, die korrekt zu sein scheint) zu Tisch mit Scan table2 sowie tabelle1.

Wie Sie sagen, dass Sie die Indizes nicht ändern können, müssen Sie die Abfrage ändern. Soweit ich das beurteilen kann, gibt es nur eine realistische Alternative ...

SELECT
   col1, col2
FROM
   table2
FULL OUTER JOIN
   table1
      ON table1.person_uid = table2.person_uid
      AND table1.period = table2.period
WHERE
   table1.person_uid IS NOT NULL

hier Die Hoffnung ist, dass Sie table2 Scan für jede einzelne Kombination von (person_uid, Zeitraum), aber die Verwendung von Indizes für tabelle1 machen. (Im Gegensatz zu scannen tabelle1 und die Nutzung von Indizes für table2, das, was ich aus der Abfrage zu erwarten.)

Wenn tabelle1 nicht entsprechenden Indizes haben, werden Sie jedoch sehr unwahrscheinlich, dass überhaupt keine Leistungsverbesserung sehen ...

Dems.

In einem der Updates der OP erklärt, dass er tatsächlich Ansichten nicht Tabellen abfragen. In diesem Fall könnte die Leistung gut direkt erhöht werden, indem die Tabellen abfragt er vor allem braucht, wenn die Ansichten zu vielen anderen Tabellen komplex und kommen sind, die er braucht keine Informationen enthalten, oder sie sind Ansichten, die Ansichten aufrufen.

ANSI-Join-Syntax eine sehr klare Unterscheidung zwischen bietet Joinbedingungen und FILTER Prädikate; dies ist sehr wichtig beim Schreiben von Outer-Joins. Mit den emp / dept Tabellen, Blick auf die Ergebnisse aus der folgenden zwei Outer-Joins

Q1

SELECT dname, d.deptno, e.ename, e.mgr, d.loc
FROM dept d
LEFT OUTER JOIN emp e
on  d.deptno = e.deptno
and loc in ('NEW YORK','BOSTON' )
;

DNAME              DEPTNO ENAME             MGR LOC
-------------- ---------- ---------- ---------- -------------
ACCOUNTING             10 CLARK            7839 NEW YORK
ACCOUNTING             10 KING                  NEW YORK
ACCOUNTING             10 MILLER           7782 NEW YORK
RESEARCH               20                       DALLAS
SALES                  30                       CHICAGO
OPERATIONS             40                       BOSTON

====

Q2
SELECT dname, d.deptno, e.ename, e.mgr, d.loc
FROM dept d
LEFT OUTER JOIN emp e
on  d.deptno = e.deptno
where loc in ('NEW YORK','BOSTON' )
;

DNAME              DEPTNO ENAME             MGR LOC
-------------- ---------- ---------- ---------- -------------
ACCOUNTING             10 CLARK            7839 NEW YORK
ACCOUNTING             10 KING                  NEW YORK
ACCOUNTING             10 MILLER           7782 NEW YORK
OPERATIONS             40                       BOSTON

Das erste Beispiel, Q1 zeigt ein Beispiel für „auf einer konstanten Verbindung“. Im wesentlichen wird die Filterbedingung verbinden äußeren zum Durchführen vor angewandt. So beseitigen Sie die Zeilen, die später hinzugefügt werden, als Teil der äußeren Rückseite verbinden. Es ist nicht unbedingt falsch, aber ist, dass die Abfrage, die Sie wirklich gefragt? Oft sind es die in Q2 gezeigten Ergebnisse, die erforderlich sind, wo der Filter angewendet wird, nachdem die (äußere) verbinden.

Es gibt auch eine Leistung Implikation auch für große Datenmengen. In vielen Fällen auf einem konstanten Verbindung hat intern vom Optimierungsprogramm gelöst werden, indem eine Seitenansicht zu schaffen, die in der Regel nur über eine verschachtelte Schleife optimiert werden können, kommt statt einem Hash-Join

Für Entwickler, die mit dem Oracle-Außen vertraut sind Join-Syntax, würde die Abfrage wahrscheinlich als

geschrieben wurde
SELECT dname, d.deptno, e.ename, e.mgr, d.loc
FROM dept d
        ,emp e
where  d.deptno = e.deptno(+)
and loc in ('NEW YORK','BOSTON' )

Diese Abfrage ist semantisch äquivalent wie Q2 oben.

Also zusammenfassend, ist es äußerst wichtig, das, dass Sie den Unterschied zwischen der JOIN-Klausel und der WHERE-Klausel zu verstehen, wenn das Schreiben ANSI-Outer-Joins.

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