Komplexe SQL-WHERE-Klausel: ob Logik Faktor
-
16-09-2019 - |
Frage
Ich habe eine komplexe SQL bekommt, wo Klausel, die nur komplexer bekam wegen einer Anforderung ändern. Es gibt vier grundlegende Arten von Fällen, die jeweils mit einer anderen Kombination von anderen Faktoren ab. Es ist besser lesbar (meiner Meinung nach) die vier Fälle als separate Zweige der Where-Klausel zu haben, und die redundanten Kriterien in jedem Zweig zu wiederholen. Aber ich weiß nicht, wie gut der Datenbank-Engine, dass optimieren.
Hier ist der Ausdruck in seiner redundanten Form. Ich habe die tatsächlichen Kriterien mit Buchstaben ersetzt. A ist das „Verzweigung“ Kriterium, das in vier Formen kommt. Alle Ausdrücke sind in Form field='value'
, sofern nicht anders angegeben.
A1 AND B AND C AND D
OR A2 AND B AND C AND D AND E AND F1 AND G
OR A3 AND A3a AND B AND C AND D AND E AND F1 AND G
OR A4 AND B AND C AND D AND F2
Alle der A der außer A4 sind in Form field in ('value1','value2')
. D ist field > 'value'
. G in Form field not in (subquery)
.
Hier ist der Ausdruck, einkalkuliert (glaube ich) seine dest redundante Form.
B AND C AND D AND (
A1
OR (
E AND F1 AND G AND (
A2
OR (A3 AND A3a)
)
)
OR (A4 AND F2)
Meine Frage ist, ob ich diesen Ausdruck in seinen einfachsten (dest redundant) logischen Formfaktor sollte, oder ob es in Ordnung zu halten, in es überflüssig ist, sondern auch mehr lesbare Form. Die Zieldatenbank ist Sybase, aber ich mag die Antwort für RDMBSs im Allgemeinen kennen.
Lösung
In einer RDBMS
Welt würde ich nicht viel Redundanz stören, Effizienz ist hier wichtiger.
In Ihrem Fall würde ich UNION
alle vier Anfragen A
die als Top-Zustand verwendet wird, wie folgt aus:
SELECT *
FROM mytable
WHERE A1 AND B AND C
UNION
SELECT *
FROM mytable
WHERE A2 AND B AND C AND D AND E AND F1 AND G
…
Ich habe nicht in Sybase
seit mehr als 7
Jahren, aber in allen wichtigen RDBMS
des UNION
die effizienter sind als OR
ist.
Lesen Sie diesen Artikel in meinem Blog für Annäherung an ein silimar Problem in Oracle
:
- Auswählen des niedrigsten Wert : effiziente Nutzung von
UNION
inOracle
und auch dieser Artikel für den Vergleich des UNION
gegen OR
in MySQL
:
- Auswählen Freunde : Effizienz
UNION
im Vergleich zu einem vonOR
inMySQL
ich denke, diese Ansätze für Sybase
zu gut funktionieren wird.
Sie müssen auch in Ihren Bedingungen verwendeten Indizes für Spalten erstellen von UNION
des profitieren
Update:
Da Bedingung G
eine Unterabfrage ist, kann es wahrscheinlich sein, dass es eine HASH JOIN
schnell ausführen muss. HASH JOIN
erfordert einen vollständigen Scan aller ungefilterten Werte, deshalb ist es wahrscheinlich besser sein können alle Werte in einem einzigen Fullscan zu filtern und dann eine HASH JOIN
ausführen:
SELECT *
FROM (
SELECT *
FROM foo
WHERE condition_set_1
UNION
SELECT *
FROM foo
WHERE condition_set_2_but_no_g
…
) q
WHERE G
Um weitere Urteile zu fällen, wird es viel besser, die Abfrage selbst zu sehen, wirklich.
Andere Tipps
Wenn ich dieses Problem auf M $ SQL Server angriffe, würde ich es so, wie schreibe ich wollte und Blick auf dem Abfrageausführungsplan. Wenn es (a) lief langsam und (b) hatte einen schlechten Ausführungsplan, dann würde ich Refactoring und zu dokumentieren. Nicht sicher, was der Mechanismus in Sybase ist für die Anzeige, wie der Optimierer die Abfrage ausführt.
Ich würde es Refactoring. Schließlich wird dupliziert Logik, die Sie auf Probleme stoßen. Das zweite Beispiel kann ein paar Sekunden länger dauern zu verstehen, aber im großen Umfang der Dinge ist es leichter zu sehen, was los ist, wie Sie schnell auf dem gesamten Klausel where aussehen und beginnen, zu bestimmen, was, was wirkt.