Postgres: оптимизация одновременных обновлений строк - PullRequest
0 голосов
/ 05 апреля 2019

ПРОБЛЕМА

Я работаю с PostgreSQL v10 + golang, и у меня есть, как мне кажется, очень распространенная проблема SQL:

  • У меня есть таблица 'counters', который имеет целочисленные столбцы current_value и max_value.
  • Строго говоря, однажды current_value >= max_value я бы хотел отбросить запрос.
  • У меня есть несколько стручков Kubernetes, которые длякаждый вызов API может увеличивать current_value из той же строки (в худшем случае) в таблице счетчиков на 1 (можно рассматривать как одновременное обновление одной и той же БД с распределенных хостов).

В моей текущей и наивной реализации несколько UPDATES для одной и той же строки естественным образом блокируют друг друга (уровень изоляции «передается на чтение», если это имеет значение).В худшем случае, у меня около 10+ запросов в секунду, которые обновляют одну и ту же строку.Это создает бутылочное горлышко и ухудшает производительность, которую я не могу себе позволить.


ВОЗМОЖНОЕ РЕШЕНИЕ

Я думал о нескольких идеях, чтобы решить эту проблему, но все они жертвуют целостностью или производительностью.Единственный, который поддерживает оба, звучит не очень чисто, для этой, казалось бы, общей проблемы:

Пока счетчик current_value находится на относительно безопасном расстоянии от max_value (дельта> 100), отправьтезапрос на обновление канала, который будет сбрасываться примерно каждую секунду работником, который будет агрегировать обновления и запрашивать их сразу.В противном случае (delta <= 100) выполните обновление в контексте транзакции (и столкнитесь с узким местом, но в меньшем количестве случаев).Это будет увеличивать количество запросов на обновление до тех пор, пока предел почти не будет достигнут, эффективно устраняя узкое место. </p>


Это, вероятно, будет работать для решения моей проблемы.Тем не менее, я не могу не думать, что есть более эффективные способы решения этой проблемы.

Я не нашел отличного решения в Интернете, и хотя мой эвристический метод работал бы, он чувствовал себя нечистым и ему не хватало целостности.

Творческие решения приветствуются!


Редактировать:

Благодаря совету @ laurenz-albe я попытался сократить продолжительность обновления до места, где появляется строказаблокирован для фиксации транзакции.Передача всех ОБНОВЛЕНИЙ до конца транзакции, похоже, сделала свое дело.Теперь я могу обрабатывать более 100 запросов в секунду и поддерживать целостность!

1 Ответ

1 голос
/ 05 апреля 2019

10 одновременных обновлений в секунду - смехотворно мало.Просто убедитесь, что транзакции настолько короткие, насколько это возможно, и это не будет проблемой.

Ваша самая большая проблема будет VACUUM, так как множество обновлений - наихудшая возможная нагрузка для PostgreSQL.Убедитесь, что вы создали таблицу с fillfactor из 70 или около того, а current_value является не проиндексированным, так что вы получаете ГОРЯЧИЕ обновления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...