Огромен IN
списъкът е много неефективен. PostgreSQL в идеалния случай би трябвало да го идентифицира и да го превърне в релация, към която прави анти-съединяване, но в този момент плановщикът на заявките не знае как да направи това и времето за планиране, необходимо за идентифициране на този случай, ще струва всяка заявка, която използва NOT IN
разумно, така че проверката трябва да е много евтина. Вижте този по-ранен много по-подробен отговор по темата
.
Както Дейвид Олдридж писа, това се решава най-добре, като се превърне в анти-съединяване. Бих го написал като съединение върху VALUES
списък просто защото PostgreSQL е изключително бърз при анализиране на VALUES
списъци в релации, но ефектът е същият:
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;
За достатъчно голям набор от стойности може дори да е по-добре да създадете временна таблица, COPY
вкарвайки стойностите в него, създавайки PRIMARY KEY
върху него и присъединяване към него.
Още възможности, разгледани тук:
https://stackoverflow.com/a/17038097/398670