Мы запускаем веб-приложение, в котором в среднем 10 000 активных пользователей, обслуживаемое 6 веб-узлами и поддерживаемое Postgres 9.4.6.
Наш инструмент мониторинга определил нижеприведенный медленный запрос, который часто имеетнедопустимое время отклика, иногда вызывающее сбои в последние дни.
Это небольшая таблица, внутренняя реализация последовательности, в основном (устаревшее приложение), отслеживающая уникальные идентификаторы для других таблиц:
CREATE TABLE ids_for_records
(
tableid integer NOT NULL,
id bigint NOT NULL,
CONSTRAINT ids_for_records_pk PRIMARY KEY (tableid)
)
WITH (
OIDS=FALSE
);
В этой таблице всего около 200 записей.Наши узлы веб-приложений используют этот запрос, чтобы получить пакет идентификаторов, предназначенных исключительно для себя:
UPDATE ids_for_records
SET id = id + <batchsize>
WHERE tableid = <unique-internal-table-id>
RETURNING id;
Мне нужно выяснить, почему производительность этого запроса значительно упала в последние дни:в среднем около 1 секунды, но иногда и 30-60 секунд.Во время высокой нагрузки все узлы выполняют одни и те же запросы параллельно для нескольких соединений.
ОБНОВЛЕНИЕ : Запрос информации о блокировках (из pg_lock, pg_class и pg_stat_activity), удерживаемых одним (медленный запрос показал, что точно такой же запрос из других транзакций, которые ожидаются.Таким образом, у нас есть одновременные транзакции, пытающиеся обновить (увеличить значение идентификатора) одну и ту же строку, таким образом, одна активная со всеми необходимыми блокировками блокирует все остальные.
В противном случае база данных исправна, наша операционная команда не обнаружила никаких проблем с хранилищем, памятью или соединениями;однако размер другой таблицы недавно достиг 64 ГБ, что может быть связано с этим.
Кто-нибудь знает, что может вызвать такое снижение производительности?Загрузка такая же, как и раньше, но этот запрос на узкое место работает примерно в 5 раз медленнее, чем раньше.