Ich habe vor einigen Tagen nach einer SQL-Optimierung darüber nachgedacht. Ich denke, wir können uns darauf einigen, dass SQL eine "deklarative Sprache" in der Definition von Wikipedia ist:
Programmierparadigma, das die Logik der Berechnung ausdrückt, ohne den Steuerungsfluss zu beschreiben
Wenn Sie sich vorstellen, wie viele Dinge hinter den Kulissen erledigt werden (Betrachten von Statistiken, Entscheiden, ob ein Index nützlich ist, Suchen nach einem verschachtelten, zusammengeführten oder Hash-Join usw.), müssen Sie zugeben, dass wir nur ein hohes Niveau angeben Logik, und die Datenbank kümmerte sich um alle Low-Level-Kontrollflusslogik.
Auch in diesem Szenario benötigt der Datenbankoptimierer manchmal einige "Hinweise" vom Benutzer, um die besten Ergebnisse zu erzielen.
Eine andere gebräuchliche Definition von "deklarativer" Sprache ist (ich kann keine autorisierende Quelle finden):
Programmierparadigma, das das gewünschte Ergebnis der Berechnung ausdrückt, ohne die Schritte zu beschreiben, um es zu erreichen (auch mit "beschreiben, was, nicht wie" abgekürzt)
Wenn wir diese Definition akzeptieren, stoßen wir auf die vom OP beschriebenen Probleme.
Das erste Problem ist, dass SQL uns mehrere gleichwertige Möglichkeiten bietet, "dasselbe Ergebnis" zu definieren. Wahrscheinlich ist das ein notwendiges Übel: Je mehr Ausdruckskraft wir einer Sprache verleihen, desto wahrscheinlicher ist es, dass es verschiedene Möglichkeiten gibt, dasselbe auszudrücken.
Als Beispiel wurde ich einmal gebeten, diese Abfrage zu optimieren:
SELECT Distinct CT.cust_type, ct.cust_type_description
from customer c
INNER JOIN
Customer_type CT on c.cust_type=ct.cust_type;
Da die Typen viel kleiner waren als die des Kunden und ein Index auf dem cust_type
Kundentisch vorhanden war, habe ich eine große Verbesserung erzielt, indem ich ihn folgendermaßen umgeschrieben habe:
SELECT CT.cust_type, ct.cust_type_description
from Customer_type CT
Where exists ( select 1 from customer c
Where c.cust_type=ct.cust_type);
In diesem speziellen Fall, als ich den Entwickler fragte, was er erreichen wolle, sagte er mir: "Ich wollte alle Kundentypen, für die ich mindestens einen Kunden hatte", das ist übrigens genau die Beschreibung der Optimierungsabfrage.
Wenn ich also eine gleichwertige und effizientere Abfrage finden könnte, warum kann das Optimierungsprogramm nicht dasselbe tun?
Ich vermute, dass es zwei Hauptgründe gibt:
SQL drückt Logik aus:
Da SQL eine übergeordnete Logik ausdrückt, möchten wir wirklich, dass der Optimierer uns und unsere Logik überlistet? Ich würde begeistert "Ja" rufen, wenn ich nicht immer den Optimierer zwingen müsste, den effizientesten Ausführungspfad auszuwählen. Ich denke, die Idee könnte sein, dem Optimierer zu erlauben, sein Bestes zu geben (und auch unsere Logik zu überarbeiten), uns aber einen "Hinweismechanismus" zu geben, um zu retten, wenn etwas verrückt wird (es wäre, als hätte man das Rad + Bremsen ein autonomes Auto).
Mehr Auswahl = mehr Zeit
Selbst der beste RDBMS-Optimierer testet nicht ALLE möglichen Ausführungspfade, da sie sehr schnell sein müssen: Wie gut wäre es, eine Abfrage von 100 ms auf 10 ms zu optimieren, wenn ich jedes Mal 100 ms für die Auswahl des besten Pfads aufwenden müsste? Und das mit dem Optimierer, der unsere "High-Level-Logik" respektiert. Wenn auch alle entsprechenden SQL-Abfragen getestet werden sollen, kann die Optimierungszeit um ein Vielfaches anwachsen.
Ein weiteres gutes Beispiel für das Umschreiben von Abfragen, zu dem kein RDBMS in der Lage ist, ist (aus diesem interessanten Blog-Beitrag ).
SELECT t1.id, t1.value, SUM(t2.value)
FROM mytable t1
JOIN mytable t2
ON t2.id <= t1.id
GROUP BY t1.id, t1.value;
als kann so geschrieben werden (analytische Funktionen erforderlich)
SELECT id, value, SUM(t1.value) OVER (ORDER BY id)
FROM mytable
select whatever from sometable where FKValue in (select FKValue from sometable_2 where other_value = :param)
. Es sollte trivial sein zu sehen, wie man das mit aexists
oder a wiedergibtjoin
.