it-swarm.com.de

Postgres JOIN-Bedingungen vs WHERE-Bedingungen

Postgres Neuling hier.

Ich frage mich, ob diese Abfrage optimiert ist oder nicht. Ich habe versucht, nur die Werte zu verbinden, die zu 100% erforderlich sind, und alle dynamischen Bedingungen in der WHERE-Klausel zu belassen. Siehe unten.

SELECT *
    FROM
      myapp_employees
    JOIN myapp_users ON
      myapp_users.user_id=myapp_employees.user_id
    JOIN myapp_contacts_assoc ON
      myapp_contacts_assoc.user_id=myapp_users.user_id
    JOIN myapp_contacts ON
      myapp_contacts.contact_id=myapp_contacts_assoc.contact_id
    WHERE
      myapp_contacts.value='[email protected]' AND
      myapp_contacts.type=(1)::INT2 AND
      myapp_contacts.is_primary=(1)::INT2 AND
      myapp_contacts.expired_at IS NULL AND
      myapp_employees.status=(1)::INT2 AND
      myapp_users.status=(1)::INT2
    LIMIT 1;

Hinweis: Für den Kontext prüft dieser Prozess, ob ein Benutzer auch ein Mitarbeiter ist (erhöhte Berechtigungen/anderer Benutzertyp).

Wie auch immer, ist das der richtige Weg? Sollte JOIN ON weitere Anweisungen enthalten, z. B. das Überprüfen auf expired_at IS NULL? Warum oder warum ist dies nicht sinnvoll?

9
Dan

Logisch, es macht überhaupt keinen Unterschied, ob Sie Bedingungen in die Join-Klausel eines INNER JOIN oder in die WHERE -Klausel desselben SELECT einfügen. . Der Effekt ist der gleiche.

(Nicht der Fall für OUTER JOIN!)

Während des Betriebs mit Standardeinstellungen spielt es auch keine Rolle für den Abfrageplan oder die Leistung. Postgres kann Joins und JOIN & WHERE Bedingungen bei der Suche nach dem besten Abfrageplan neu anordnen - solange die Anzahl der Tabellen nicht größer als join_collapse_limit (Standard 8). Einzelheiten:

Für Lesbarkeit und Wartbarkeit ist es sinnvoll, Bedingungen, die Tabellen verbinden, in die jeweilige Klausel JOIN und allgemeine Bedingungen in die Klausel WHERE einzufügen.

Ihre Anfrage sieht gut aus. Ich würde jedoch Tabellen-Aliase verwenden, um das Rauschen zu reduzieren.

Kleinigkeit:

int2 '1' oder sogar 1::int2 sind sinnvoller als (1)::INT2. Und im Vergleich zu einem Wert eines genau definierten numerischen Datentyps ist auch eine einfache numerische Konstante 1 gut genug.

13

Ein paar Punkte ..

  1. Wenn Sie in Ihrem Fall unter einer Bedingung mit demselben Namen (user_id) Beitreten, können Sie USING (user_id) anstelle von ON (a.user_id = b.user_id) verwenden. Dies verhindert auch, dass eine redundante Spalte möglicherweise ausgegeben wird (wenn Sie SELECT * In der Produktion ausführen).

  2. 1::int2 Ist problematisch. Entweder status und is_primary Und andere sind bereits int2. In diesem Fall wird das Literal 1 automatisch in int2 oder int2 in int umgewandelt, wie pg es für richtig hält. Oder wenn Sie sie als reguläre Ints speichern und sie so ablegen, als ob dies einen Unterschied in der Berechnung bewirken würde - was nicht der Fall ist, macht die Besetzung allein dies zu einem Verlust.

  3. Wenn möglich, sollte das gesamte :: int2 wahrscheinlich als boolean gespeichert werden. Dann können Sie Ihre WHERE Bedingung schreiben, um auch einfacher zu sein.

  4. Für Ihren Typ und Status möchten Sie möglicherweise einen Typ ENUM.

2
Evan Carroll