Ogromny IN
lista jest bardzo nieefektywna. PostgreSQL powinien idealnie go zidentyfikować i przekształcić w relację, na której działa anty-join, ale w tym momencie planer zapytań nie wie, jak to zrobić, a czas planowania wymagany do zidentyfikowania tego przypadku kosztowałby każde zapytanie, które używa NOT IN
rozsądnie, więc musiałaby to być bardzo tania kontrola. Zobacz tę wcześniejszą znacznie bardziej szczegółową odpowiedź na ten temat
.
Jak napisał David Aldridge, najlepiej rozwiązać ten problem, zmieniając go w anty-join. Zapisałbym to jako sprzężenie nad VALUES
lista po prostu dlatego, że PostgreSQL jest niezwykle szybki w przetwarzaniu VALUES
listy w relacje, ale efekt jest ten sam:
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;
W przypadku wystarczająco dużego zestawu wartości może być nawet lepiej utworzyć tabelę tymczasową, COPY
wpisując do niego wartości, tworząc PRIMARY KEY
na nim i dołączając do tego.
Więcej możliwości zbadanych tutaj:
https://stackoverflow.com/a/17038097/398670