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.

War es hilfreich?

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:

und auch dieser Artikel für den Vergleich des UNION gegen OR in MySQL:

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.

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