Allt beror på ...
-
Förutsatt att ingen samtidig skrivåtkomst till inblandade bord eller så kanske du måste låsa bord uteslutande eller så kanske den här vägen inte är något för dig alls.
-
Ta bort alla index (eventuellt förutom de som behövs för själva raderingen).
Återskapa dem efteråt. Det är vanligtvis mycket snabbare än inkrementella uppdateringar av index. -
Kontrollera om du har triggers som säkert kan tas bort/inaktiveras tillfälligt.
-
Refererar främmande nycklar till din tabell? Kan de raderas? Tillfälligt raderad?
-
Beroende på dina autovakuuminställningar kan hjälp med att köra
VACUUM ANALYZE
före operationen. -
Några av punkterna som listas i det relaterade kapitlet i manualen Fylla en databas kan också vara till nytta, beroende på din inställning.
-
Om du raderar stora delar av tabellen och resten får plats i RAM, kan det snabbaste och enklaste sättet vara detta:
BEGIN; -- typically faster and safer wrapped in a single transaction
SET LOCAL temp_buffers = '1000MB'; -- enough to hold the temp table
CREATE TEMP TABLE tmp AS
SELECT t.*
FROM tbl t
LEFT JOIN del_list d USING (id)
WHERE d.id IS NULL; -- copy surviving rows into temporary table
TRUNCATE tbl; -- empty table - truncate is very fast for big tables
INSERT INTO tbl
SELECT * FROM tmp; -- insert back surviving rows.
-- ORDER BY ? -- optionally order favorably while being at it
COMMIT;
På så sätt behöver du inte återskapa vyer, främmande nycklar eller andra beroende objekt. Och du får ett orördt (sorterat) bord utan uppsvälldhet.
Läs om temp_buffers
inställning i manualen. Denna metod är snabb så länge som tabellen passar in i minnet, eller åtminstone det mesta. Transaktionspaketet skyddar mot att förlora data om din server kraschar mitt under denna operation.
Kör VACUUM ANALYZE
i efterhand. Eller VACUUM FULL ANALYZE
om du vill få den till minsta storlek (tar exklusivt lås). För stora tabeller överväg alternativen CLUSTER
/ pg_repack
eller liknande:
- Optimera Postgres tidsstämpelfrågeintervall
För små tabeller, en enkel DELETE
istället för TRUNCATE
är ofta snabbare:
DELETE FROM tbl t
USING del_list d
WHERE t.id = d.id;
Läs Anteckningar avsnitt för TRUNCATE
i manualen. I synnerhet (som Pedro också påpekade i sin kommentar):
TRUNCATE
kan inte användas på en tabell som har främmande nyckelreferenser från andra tabeller, om inte alla sådana tabeller också trunkeras i samma kommando. [...]
Och:
TRUNCATE
kommer inte att aktivera någonON DELETE
utlösare som kan finnas för tabellerna.