En enorm IN
listan är mycket ineffektiv. PostgreSQL borde idealiskt identifiera det och förvandla det till en relation som det gör en anti-join på, men vid det här laget vet frågeplaneraren inte hur man gör det, och den planeringstid som krävs för att identifiera detta fall skulle kosta varje fråga som använder NOT IN
förnuftigt, så det måste vara en mycket låg kostnadskontroll. Se det här tidigare mycket mer detaljerade svaret om ämnet
.
Som David Aldridge skrev löses detta bäst genom att förvandla det till en anti-join. Jag skulle skriva det som en sammanfogning över en VALUES
lista helt enkelt för att PostgreSQL är extremt snabb på att analysera VALUES
listar i relationer, men effekten är densamma:
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 en tillräckligt stor uppsättning värden kan det till och med vara bättre att skapa en tillfällig tabell, COPY
lägga in värdena i den och skapa en PRIMARY KEY
på den, och gå med på det.
Fler möjligheter utforskas här:
https://stackoverflow.com/a/17038097/398670