Det hele afhænger ...
-
Forudsat ingen samtidig skriveadgang til involverede borde, eller du skal muligvis udelukkende låse borde, ellers er denne rute måske slet ikke noget for dig.
-
Slet alle indekser (evt. undtagen dem, der er nødvendige for selve sletningen).
Genopret dem bagefter. Det er typisk meget hurtigere end trinvise opdateringer af indekser. -
Tjek, om du har triggere, der sikkert kan slettes/deaktiveres midlertidigt.
-
Refererer fremmednøgler til din tabel? Kan de slettes? Slettet midlertidigt?
-
Afhængigt af dine autovakuumindstillinger kan det hjælp til at køre
VACUUM ANALYZE
før operationen. -
Nogle af punkterne, der er anført i det relaterede kapitel i manualen Populering af en database kan også være til nytte, afhængigt af din opsætning.
-
Hvis du sletter store dele af bordet, og resten passer ind i RAM, kan den hurtigste og nemmeste måde være denne:
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å denne måde behøver du ikke at genskabe visninger, fremmednøgler eller andre afhængige objekter. Og du får et uberørt (sorteret) bord uden oppustethed.
Læs om temp_buffers
indstilling i manualen. Denne metode er hurtig, så længe bordet passer ind i hukommelsen, eller i det mindste det meste af det. Transaktionsindpakningen beskytter mod at miste data, hvis din server går ned midt i denne operation.
Kør VACUUM ANALYZE
bagefter. Eller VACUUM FULL ANALYZE
hvis du ønsker at bringe den til minimum størrelse (tager eksklusiv lås). For store tabeller overveje alternativerne CLUSTER
/ pg_repack
eller lignende:
- Optimer Postgres tidsstempelforespørgselsinterval
For små tabeller, en simpel DELETE
i stedet for TRUNCATE
er ofte hurtigere:
DELETE FROM tbl t
USING del_list d
WHERE t.id = d.id;
Læs Bemærkningerne sektion for TRUNCATE
i manualen. Især (som Pedro også påpegede i sin kommentar):
TRUNCATE
kan ikke bruges på en tabel, der har fremmednøglereferencer fra andre tabeller, medmindre alle sådanne tabeller også afkortes i den samme kommando. [...]
Og:
TRUNCATE
vil ikke udløse nogen ON DELETE
triggere, der kan eksistere for tabellerne.