Un enorme IN
elenco è molto inefficiente. PostgreSQL idealmente dovrebbe identificarlo e trasformarlo in una relazione su cui esegue un anti-join, ma a questo punto il pianificatore di query non sa come farlo e il tempo di pianificazione richiesto per identificare questo caso costerebbe ogni query che utilizza NOT IN
ragionevolmente, quindi dovrebbe essere un controllo a basso costo. Vedi questa precedente risposta molto più dettagliata sull'argomento
.
Come ha scritto David Aldridge, è meglio risolverlo trasformandolo in un anti-join. Lo scriverei come join su un VALUES
list semplicemente perché PostgreSQL è estremamente veloce nell'analisi di VALUES
elenca in relazioni, ma l'effetto è lo stesso:
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;
Per un insieme di valori sufficientemente ampio potresti anche essere meglio creare una tabella temporanea, COPY
inserendo i valori al suo interno, creando una PRIMARY KEY
su di esso, e unirmi a quello.
Altre possibilità esplorate qui:
https://stackoverflow.com/a/17038097/398670