MVCC
Първо, ако "нормалните операции" се състоят от SELECT
заявки, моделът MVCC ще се погрижи за това автоматично. UPDATE
не блокира SELECT
и обратно. SELECT
вижда само ангажирани данни (или това, което е направено в същата транзакция), така че резултатът от голямото UPDATE
остава невидим за други транзакции, докато не бъде направен (ангажиран).
Изпълнение/раздуване
Ако нямате други обекти, препращащи към тази таблица,
и нямате едновременни операции за запис (които биха били загубени!),
и можете да си позволите много къса изключителна ключалка на масата,
и имате допълнително дисково пространство, разбира се:
Можете да намалите заключването до минимум, като създадете актуализирана версия на таблицата във фонов режим. Уверете се, че има всичко за да бъде заместник, след което изхвърлете оригинала и преименувайте фалшивото.
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;
Използвам CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS)
, защото (цитирайки ръководството тук):
Ненулевите ограничения винаги се копират в новата таблица.
CHECK
ограниченията ще бъдат копирани само акоINCLUDING CONSTRAINTS
е посочено; други типове ограничения никога няма да бъдат копирани.
Уверете се, че новата маса е готова. След това:
DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;
Резултатът е много кратък период от време, при който таблицата е изключително заключена.
Това всъщност е само за производителност. Създава нова маса без никакво раздуване доста бързо. Ако имате външни ключове или изгледи, все още можете да вървите по този път, но трябва да подготвите скрипт за пускане и пресъздаване на тези обекти, което потенциално създава допълнителни изключителни ключалки.
Едновременно записвания
С едновременни операции по запис, наистина всичко, което можете да направите, е да разделите актуализацията си на парчета. Не можете да направите това в една транзакция, тъй като заключванията се освобождават само в края на транзакция.
Вие можете използвайте dblink , който може да стартира независими транзакции в друга база данни, включително самата нея. По този начин можете да направите всичко с едно DO
оператор или функция plpgsql с цикъл. Ето един слабо свързан отговор с повече информация за dblink:
- Изхвърлете или създайте база данни от съхранената процедура в PostgreSQL
Вашият подход с курсори
Курсорът във функцията няма да ви купи нищо . Всяка функция се включва автоматично в транзакция и всички заключвания се освобождават само в края на транзакцията. Дори ако сте използвали CLOSE cursor
(което не правите) това би освободило само някои ресурси, но не освободете придобитите ключалки на масата. Цитирам ръководството:
CLOSE
затваря портала под отворен курсор. Това може да се използва за освобождаване на ресурси по-рано от края на транзакцията или за освобождаване на променливата на курсора, за да бъде отворена отново.
Ще трябва да стартирате отделно транзакциите или (зло)използвайте dblink, който прави това вместо вас.