SQL Frage von Joel Spolsky Artikel

8

Aus Joel Spolskys Artikel zu undichten Abstraktionen:

  

[C] bestimmte SQL-Abfragen sind tausendmal langsamer als andere logisch äquivalente Abfragen. Ein bekanntes Beispiel dafür ist, dass einige SQL-Server wesentlich schneller sind, wenn Sie "where a = b und b = c und a = c" angeben, als wenn Sie nur "where a = b und b = c" angeben, obwohl das Ergebnis gesetzt ist ist das gleiche.

Kennt jemand die Details?

    
jason 29.12.2008, 03:34
quelle

3 Antworten

24

Offensichtlich sind a = b und b = c = & gt; a = c - dies steht im Zusammenhang mit der transitiven Schließung. Der Punkt, den Joel machte, ist, dass einige SQL-Server die Optimierung von Abfragen schlecht beherrschen, sodass einige der SQL-Abfragen wie im Beispiel mit "zusätzlichen" Qualifikationsmerkmalen geschrieben werden können.

Denken Sie in diesem Beispiel daran, dass sich a, b und c wie oben häufig auf verschiedene Tabellen beziehen und Operationen wie a = b als Joins ausgeführt werden. Angenommen, die Anzahl der Einträge in Tabelle a ist 1000, b ist 500 und c ist 20. Dann benötigt der Join von a, b einen Zeilenvergleich von 1000x500 (das ist mein dummes Beispiel; in der Praxis könnten viel bessere Join-Algorithmen die Komplexität reduzieren) eine Menge), und b, c benötigt 500x20 Vergleiche. Ein optimierender Compiler wird bestimmen, dass der Join von b, c zuerst ausgeführt werden soll, und dann sollte das Ergebnis auf a = b verknüpft werden, da weniger erwartete Zeilen mit b = c vorhanden sind. Insgesamt ergeben sich für (b = c) bzw. (a = b) etwa 500x20 + 500x1000 Vergleiche. Danach müssen Schnittpunkte zwischen den zurückgegebenen Zeilen berechnet werden (ich denke auch über Joins, aber nicht sicher).

Angenommen, der Sql-Server könnte ein Logik-Inferenz-Modul haben, das auch folgert, dass dies a = c bedeutet. Dann würde es wahrscheinlich eine Verbindung von b, c ausführen und dann eine Verbindung von a, c (wiederum ist dies ein hypothetischer Fall). Dies würde 500 × 20 + 1000 × 20 Vergleiche und danach Kreuzungsberechnungen erfordern. Wenn # (a = c) kleiner ist (aufgrund einiger Domänenkenntnisse), ist die zweite Abfrage viel schneller.

Insgesamt ist meine Antwort zu lang geworden, aber das bedeutet, dass die Optimierung von SQL-Abfragen keine triviale Aufgabe ist, und das ist der Grund, warum einige SQL-Server es nicht sehr gut machen.

Mehr finden Sie unter Ссылка oder von einigen, die auf Datenbanken warten, die das lesen.

Aber philosophisch gesehen sollte SQL (als Abstraktion) alle Aspekte der Implementierung verbergen. Es sollte deklarativ sein (ein SQL-Server kann selbst sql-Abfrageoptimierungstechniken verwenden, um die Abfrage neu zu formulieren, um sie effizienter zu machen). Aber in der realen Welt ist es nicht so - oft müssen die Datenbankabfragen von Menschen neu geschrieben werden, um sie effizienter zu machen.

Insgesamt ist der Punkt des Artikels, dass eine Abstraktion nur so gut sein kann und keine Abstraktion perfekt ist.

    
amit_grepclub 29.12.2008, 03:59
quelle
15

Hier ist eine einfachere Erklärung, wo alles in einer Tabelle ist.

Angenommen, A und C sind beide indiziert, B nicht. Wenn der Optimierer nicht erkennen kann, dass A = C ist, muss er das nicht indizierte B für beide WHERE-Bedingungen verwenden.

Aber wenn Sie dann dem Server mitteilen, dass a = c ist, kann er diesen Filter zuerst effizient anwenden und die Größe des Arbeitssatzes stark reduzieren.

    
Joel Coehoorn 29.12.2008 15:21
quelle
1

Ich denke, das "bestimmte" Wort ist hier der operative Ausdruck. Damit der Optimierer wirklich versteht, dass a = c, müsste er die Gleichheit von a vollständig analysieren und dann in einer transitiven Beziehung mit "c" verbinden, um die Beziehung abzuleiten.

Ich denke, dass SQL-Optimierer dies in Zukunft intelligent machen könnten (wenn sie es nicht schon sind), also IMO, das ist nicht wirklich eine allgemeine Aussage von Joel.

    
Dave Markle 29.12.2008 03:56
quelle

Tags und Links