sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL:Hoe kom ik erachter dat er ontbrekende getallen in een kolom zijn met behulp van Genereer_series()?

Gegeven voorbeeldgegevens:

create table results ( commandid integer primary key);
insert into results (commandid) select * from generate_series(1,1000);
delete from results where random() < 0.20;

Dit werkt:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE NOT EXISTS (SELECT 1 FROM results WHERE commandid = s.i);

net als deze alternatieve formulering:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
LEFT OUTER JOIN results ON (results.commandid = s.i) 
WHERE results.commandid IS NULL;

Beide bovenstaande lijken te resulteren in identieke queryplannen in mijn tests, maar u moet deze vergelijken met uw gegevens in uw database met behulp van EXPLAIN ANALYZE om te zien welke het beste is.

Uitleg

Merk op dat in plaats van NOT IN Ik heb NOT EXISTS gebruikt met een subquery in één formulering en een gewone OUTER JOIN in de andere. Het is veel gemakkelijker voor de DB-server om deze te optimaliseren en het vermijdt de verwarrende problemen die kunnen optreden met NULL s in NOT IN .

Ik gaf aanvankelijk de voorkeur aan de OUTER JOIN formulering, maar in ieder geval in 9.1 met mijn testgegevens de NOT EXISTS formulier optimaliseert naar hetzelfde plan.

Beide zullen beter presteren dan de NOT IN formulering hieronder wanneer de reeks groot is, zoals in uw geval. NOT IN gebruikt om Pg te verplichten om een ​​lineaire zoekopdracht uit te voeren van de IN lijst voor elke tuple die wordt getest, maar onderzoek van het queryplan suggereert dat Pg misschien slim genoeg is om het nu te hashen. De NOT EXISTS (omgevormd tot een JOIN door de queryplanner) en de JOIN beter werken.

De NOT IN formulering is zowel verwarrend in de aanwezigheid van NULL commandid s en kan inefficiënt zijn:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE s.i NOT IN (SELECT commandid FROM results);

dus ik zou het vermijden. Met 1.000.000 rijen voltooiden de andere twee in 1,2 seconden en de NOT IN formulering liep CPU-gebonden totdat ik me verveelde en het annuleerde.



  1. Geef een kolom alleen weer als deze niet null is

  2. Wat is de gemakkelijkste manier om de start- en einddatum van een sprint uit de JIRA-database te halen?

  3. Vang dubbele invoer Uitzondering

  4. Hoe geef ik een lijst met ID's door aan de MySQL-opgeslagen procedure?