Оптимізація паралельних оновлень у Postgres


9

Я виконую одночасні запити Postgres на зразок цього:

UPDATE foo SET bar = bar + 1 WHERE baz = 1234

Кожен запит впливає на фіксовану кількість рядків K, і я не можу знайти спосіб примусово виконувати порядок, в якому рядки оновлюються, і закінчується тупиком. В даний час я вирішую проблему, виконуючи замовлення вручну, але це означає, що мені потрібно виконати набагато більше запитів, ніж зазвичай, одночасно підвищуючи складність пошуку з O (log N + K) до O (K log N).

Чи є спосіб покращити продуктивність без закінчення вразливих до тупиків? Я підозрюю, що заміна (baz)індексу (baz, id)індексом може спрацювати за умови, що Postgres оновлює рядки в тому ж порядку, в якому їх відсканував, чи варто цьому підходити?


Я пропоную вам додати CREATE TABLEкод.
ypercubeᵀᴹ

Відповіді:


15

Існує немає ORDER BYв SQL UPDATEкоманді. Postgres оновлює рядки у довільному порядку:

Щоб уникнути тупикових ситуацій з абсолютною впевненістю, ви можете запускати свої висловлювання в ізоляційній послідовності угод . Але це дорожче, і вам потрібно підготуватися до повторення команд щодо відмови серіалізації.

Ваш найкращий спосіб дії - це, ймовірно, блокування явним чином SELECT ... ORDER BY ... FOR UPDATEу підзапиті або окремому SELECTу транзакції - за замовчуванням рівень ізоляції "читання здійснено". Цитуючи Тома Лейн на pgsql-загальному :

Має бути все гаразд - блокування FOR UPDATE - це завжди останній крок у трубопроводі SELECT.

Це має зробити цю роботу:

BEGIN;

SELECT 1
FROM   foo 
WHERE  baz = 1234
ORDER  BY bar
FOR    UPDATE;

UPDATE foo
SET    bar = bar + 1
WHERE  baz = 1234;

COMMIT;

Багатоцільовий індекс на (baz, bar)може бути ідеальним для продуктивності. Але оскільки bar, очевидно, багато оновлюється , індекс з одним стовпцем на просто (baz)може бути ще кращим. Залежить від пари факторів. Скільки рядків на кожен baz? Чи можливі оновлення HOT без бездротового індексу? ...

Якщо baz оновлюється одночасно, є ще навряд чи кут випадку ймовірність конфліктів (в документації) :

Можливо, що SELECTкоманда, що працює на READ COMMITTED рівні ізоляції транзакцій, використовує ORDER BYта блокуючий пункт, щоб повернути рядки з порядку. ...

Крім того, якщо у вас виникне унікальне обмеження bar, враховуйте DEFERRABLEобмеження, щоб уникнути унікальних порушень в межах однієї команди. Відповідна відповідь:


1
ЯКЩО я idзамість цього замовляю або якийсь інший унікальний стовпець bar, не повинно бути кутового корпусу чи покази ефективності, правда?
Олексій Аверченко

@AlexeiAverchenko: Так, унікальний стовпець, який ніколи не оновлюється, був би ідеальним для цього - і індекс багатоколінок, що включає цей стовпець на другій позиції.
Ервін Брандстеттер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.