Ein riesiges IN
Liste ist sehr ineffizient. PostgreSQL sollte es idealerweise identifizieren und in eine Beziehung umwandeln, für die es einen Anti-Join durchführt, aber an diesem Punkt weiß der Abfrageplaner nicht, wie das geht, und die Planungszeit, die erforderlich ist, um diesen Fall zu identifizieren, würde jede Abfrage so viel kosten verwendet NOT IN
vernünftigerweise, also müsste es ein sehr kostengünstiger Scheck sein. Siehe diese frühere viel ausführlichere Antwort zu diesem Thema
.
Wie David Aldridge schrieb, lässt sich dies am besten lösen, indem man es in einen Anti-Join umwandelt. Ich würde es als Join über VALUES
schreiben einfach deshalb auflisten, weil PostgreSQL beim Parsen von VALUES
extrem schnell ist Listen in Relationen, aber der Effekt ist derselbe:
SELECT entityid
FROM entity e
LEFT JOIN level1entity l1 ON l.level1id = e.level1_level1id
LEFT JOIN level2entity l2 ON l2.level2id = l1.level2_level2id
LEFT OUTER JOIN (
VALUES
(1377776),(1377792),(1377793),(1377794),(1377795),(1377796)
) ex(ex_entityid) ON (entityid = ex_entityid)
WHERE l2.userid = 'a987c246-65e5-48f6-9d2d-a7bcb6284c8f'
AND ex_entityid IS NULL;
Für einen ausreichend großen Satz von Werten ist es vielleicht sogar besser, eine temporäre Tabelle zu erstellen, COPY
ing die Werte hinein und erzeugt einen PRIMARY KEY
darauf und schließe mich dem an.
Weitere Möglichkeiten wurden hier erkundet:
https://stackoverflow.com/a/17038097/398670