sql >> Database >  >> RDS >> PostgreSQL

De beste manier om miljoenen rijen op ID te verwijderen

Het hangt allemaal af ...

  • Ervan uitgaande dat geen gelijktijdige schrijftoegang naar betrokken tafels of misschien moet je de tafels exclusief vergrendelen of is deze route misschien helemaal niet voor jou.

  • Verwijder alle indexen (mogelijk behalve degene die nodig zijn voor het verwijderen zelf).
    Maak ze daarna opnieuw aan. Dat is doorgaans veel sneller dan incrementele updates van indexen.

  • Controleer of je triggers hebt die veilig tijdelijk kunnen worden verwijderd/uitgeschakeld.

  • Verwijzen buitenlandse sleutels naar uw tabel? Kunnen ze worden verwijderd? Tijdelijk verwijderd?

  • Afhankelijk van uw autovacuüminstellingen kan het mogelijk hulp bij het uitvoeren van VACUUM ANALYZE voor de operatie.

  • Enkele van de punten die worden genoemd in het gerelateerde hoofdstuk van de handleiding Een database vullen kan ook nuttig zijn, afhankelijk van uw opstelling.

  • Als u grote delen van de tabel verwijdert en de rest past in het RAM-geheugen, is dit de snelste en gemakkelijkste manier:

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;

Op deze manier hoeft u geen weergaven, externe sleutels of andere afhankelijke objecten opnieuw te maken. En je krijgt een smetteloze (gesorteerde) tafel zonder opgeblazen gevoel.

Lees over de temp_buffers instelling in de handleiding. Deze methode is snel zolang de tabel in het geheugen past, of in ieder geval het grootste deel ervan. De transactie-wrapper beschermt tegen gegevensverlies als uw server tijdens deze bewerking crasht.

Voer VACUUM ANALYZE uit daarna. Of VACUUM FULL ANALYZE als je het naar de minimale grootte wilt brengen (neemt exclusief slot op). Overweeg voor grote tafels de alternatieven CLUSTER / pg_repack of vergelijkbaar:

  • Optimaliseer het zoekopdrachtbereik van Postgres-tijdstempel

Voor kleine tabellen, een simpele DELETE in plaats van TRUNCATE is vaak sneller:

DELETE FROM tbl t
USING  del_list d
WHERE  t.id = d.id;

Lees de Opmerkingen sectie voor TRUNCATE in de handleiding. In het bijzonder (zoals Pedro ook opmerkte in zijn commentaar):

TRUNCATE kan niet worden gebruikt op een tabel die refererende-sleutelverwijzingen heeft uit andere tabellen, tenzij al dergelijke tabellen ook worden afgekapt in dezelfde opdracht. [...]

En:

TRUNCATE zal geen ON DELETE fire afvuren triggers die kunnen bestaan ​​voor de tabellen.



  1. Deling van gehele getallen geeft 0

  2. PostgreSQL's date_trunc in mySQL

  3. Hoe kan ik selecteren uit de lijst met waarden in SQL Server?

  4. MySQL hoog CPU-gebruik