sql >> Databasteknik >  >> RDS >> PostgreSQL

Bästa sättet att ta bort miljontals rader efter ID

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ågon ON DELETE utlösare som kan finnas för tabellerna.



  1. Skapa och distribuera flera versioner av databasen genom Schema Snapshots

  2. Fördelar med NoSQL-databaser – Allt du behöver veta

  3. CTE för att få alla barn (ättlingar) till en förälder

  4. Hur man väljer en användarvänlig databas för ditt företag