sql >> Database teknologi >  >> RDS >> PostgreSQL

Postgres IKKE I ydelse

En enorm IN listen er meget ineffektiv. PostgreSQL burde ideelt set identificere det og gøre det til en relation, som det gør en anti-join på, men på dette tidspunkt ved forespørgselsplanlæggeren ikke, hvordan man gør det, og den planlægningstid, der kræves til at identificere denne sag, ville koste hver forespørgsel, der bruger NOT IN fornuftigt, så det må være en meget billig kontrol. Se dette tidligere meget mere detaljerede svar om emnet .

Som David Aldridge skrev, løses dette bedst ved at gøre det til en anti-join. Jeg ville skrive det som en joinforbindelse over en VALUES liste, simpelthen fordi PostgreSQL er ekstremt hurtig til at parse VALUES lister ind i relationer, men effekten er den samme:

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; 

For et tilstrækkeligt stort sæt værdier kan du endda være bedre stillet at oprette en midlertidig tabel, COPY ved at indsætte værdierne i det, skabe en PRIMARY KEY på det, og slutte sig til det.

Flere muligheder undersøgt her:

https://stackoverflow.com/a/17038097/398670



  1. Har du brug for hjælp til Hierarchical Mysql Query

  2. Sådan bruger du Oracle-klient 11.2 med php (xampp) på win7 x64

  3. Sådan kalder du en Oracle-funktion med en Ref Cursor som Out-parameter fra Visual Basic

  4. Sådan importeres og eksporteres CSV-filer ved hjælp af PHP og MySQL