MVCC
Ten eerste, als "normale bewerkingen" bestaan uit SELECT
query's, zal het MVCC-model dit automatisch regelen. UPDATE
blokkeert SELECT
niet en vice versa. SELECT
ziet alleen vastgelegde gegevens (of wat er in dezelfde transactie is gedaan), dus het resultaat van de grote UPDATE
blijft onzichtbaar voor andere transacties totdat het is voltooid (toegezegd).
Prestatie / opgeblazen gevoel
Als je hebt geen andere objecten die naar die tabel verwijzen,
en je hebt geen gelijktijdige schrijfbewerkingen (die zouden verloren gaan!),
en je kunt je een heel kort exclusief slot op tafel veroorloven,
en je hebt natuurlijk de extra schijfruimte:
Je zou de vergrendeling tot een minimum kunnen beperken door een bijgewerkte versie van de tabel op de achtergrond te maken. Zorg ervoor dat het alles heeft om een drop-in vervanging te zijn, laat dan het origineel vallen en hernoem de dupe.
CREATE TABLE tbl_new (LIKE tbl_org INCLUDING CONSTRAINTS);
INSERT INTO tbl_new
SELECT col_a, col_b, array[col] aS col_c
FROM tbl_org;
Ik gebruik CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS)
, omdat (hier de handleiding geciteerd):
Niet-null-beperkingen worden altijd naar de nieuwe tabel gekopieerd.
CHECK
beperkingen worden alleen gekopieerd alsINCLUDING CONSTRAINTS
is gespecificeerd; andere soorten beperkingen zullen nooit worden gekopieerd.
Zorg ervoor dat de nieuwe tafel klaar is. Dan:
DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;
Resulteert in een zeer kort tijdvenster, waarbij de tafel exclusief is vergrendeld.
Dit gaat eigenlijk alleen over prestaties. Het creëert vrij snel een nieuwe tafel zonder enige bloat. Als je externe sleutels of views hebt, kun je nog steeds die route volgen, maar je moet een script voorbereiden om deze objecten te laten vallen en opnieuw te maken, waardoor mogelijk extra exclusieve sloten worden gemaakt.
Gelijktijdige schrijfacties
Met gelijktijdige schrijfbewerkingen is het enige dat u kunt doen, uw update in delen opsplitsen. Dat kan niet in een enkele transactie, aangezien sloten pas aan het einde van een transactie worden vrijgegeven.
Je zou gebruik dblink , die onafhankelijke transacties op een andere database kan starten, inclusief zichzelf. Op deze manier zou je het allemaal in een enkele DO
. kunnen doen statement of een plpgsql-functie met een lus. Hier is een losjes gerelateerd antwoord met meer informatie over dblink:
- Drop of creëer database van opgeslagen procedure in PostgreSQL
Uw benadering met cursors
Een cursor in de functie zal je niets kopen . Elke functie wordt automatisch in een transactie ingesloten en alle vergrendelingen worden pas vrijgegeven aan het einde van de transactie. Zelfs als u CLOSE cursor
hebt gebruikt (wat je niet doet) het zou alleen wat middelen vrijmaken, maar niet ontgrendel de verworven sloten op de tafel. Ik citeer de handleiding:
CLOSE
sluit de portal onder een open cursor. Dit kan worden gebruikt om bronnen eerder vrij te geven dan het einde van de transactie, of om de cursorvariabele vrij te maken om opnieuw te worden geopend.
U zou apart . moeten uitvoeren transacties of (ab)gebruik dblink die dat voor u doet.