🐘 Подготовленные планы в PostgreSQL

Кто-то меня спрашивал о выгоде преподготовленных планов в «Постгресе». Наши испытания показывают, что выигрыш порядка 10—15%, что очень немало. И я уже рассказывал, что придумал рецепт как делить их в условиях «умирающего» ПХП.

Но вот какая неприятность — при подключении любого балансировщика нагрузки, совершенно неочевидно куда улетает ваш план и таблица в приложении не помогает — она единая, а серверов может быть несколько, у каждого свои планы подготовленные. Если мы начнём подготавливать его заново, а он уже есть, получим ошибку, что план уже существует.

Какой выход? Краткий ответ: пока никакой.

Самый очевидный — игнорировать такие ошибки. К сожалению, он не подойдёт — если ошибка произойдёт в транзакции, «Постгрес» её просто откатит. Второй выход — не использовать подготовленные планы. Я пока нашёл третий — мы используем планы только если уверены, что они пойдут на мастер — это запросы на изменение чего-либо.

С другой стороны у меня появилась идея — добавить в эскуэль конструкцию PREPARE IF NOT EXISTS, ребята из, с которыми я обсуждал эту идею, PostgresPro уже сделали несколько версий патча.

Основа идеи — всегда слать запрос на компиляцию плана, но если он уже был скомпилирован, ничего не делать. Мы его уже погоняли (оттуда и цифры первого абзаца), но на этом пути больше трудностей, чем себе можно представить — в частности, надо патчить ещё и продукты для балансировки и расширять его клиентский протокол.

Очень надеюсь, что патч доведут до ума и мы скоро сможем его использовать.
27 марта 2016 20:04

pavelpat (инкогнито)
27 марта 2016, 20:32

А делать savepoint перед такими запросами на поготовку запросов и делать rollback to savepoint если произошла ошибка сильно дольше, чем выигрыш от подготовки?

bolknote.ru (bolknote.ru)
27 марта 2016, 20:57, ответ предназначен pavelpat

Во-первых, правильное решение, всё же — предоставить возможность не подготавливать планы, если они уже готовы. Тем более, это в традициях Постгреса — что-то похожее есть почти во всех командах создания чего-либо.

Во-вторых, как ты думаешь, какова сложность операции отката/накатки транзакции и репликации всего этого? Не думаю, что стоит даже начинать копать в этом направлении.

hshhhhh.name (инкогнито)
27 марта 2016, 21:05

Я не знаю что такое планы в постгресе, но ведь можно делать вместо 'plan_name' костыль 'server_0_plan_name', на каждый сервер будет хранится своя копия плана

bolknote.ru (bolknote.ru)
27 марта 2016, 21:07, ответ предназначен hshhhhh.name

Как узнать сервер?

bolknote.ru (bolknote.ru)
27 марта 2016, 21:33, ответ предназначен hshhhhh.name

Я не знаю что такое планы в постгресе
Планы в «Постгресе» то же, что и в любой другой базе.

pavelpat (инкогнито)
27 марта 2016, 22:20

Во-вторых, как ты думаешь, какова сложность операции отката/накатки транзакции и репликации всего этого? Не думаю, что стоит даже начинать копать в этом направлении.
Не могу ответить однозначно, но думаю, что данные попадают на реплики только после коммита всей транзакции, а savepoint на этот механизм никак не влияет.
Насчёт стоимости savepoint'а, ниразу не слышал, что этот механизм не стоит использовать из-за каких-то проблем с производительностью. Считаю, что этот вопрос нужно изучить, прежде чем отвечать.

Олег Горбунов (инкогнито)
28 марта 2016, 04:58, ответ предназначен bolknote.ru:

Обидно еще то, как я понимаю, подготовленный план гораздо выгоднее в сложных селектах?

bolknote.ru (bolknote.ru)
28 марта 2016, 06:07, ответ предназначен Олег Горбунов

Обидно еще то, как я понимаю, подготовленный план гораздо выгоднее в сложных селектах?
Да, конечно!

bolknote.ru (bolknote.ru)
28 марта 2016, 06:08, ответ предназначен pavelpat

Насчёт стоимости savepoint'а, ни разу не слышал, что этот механизм не стоит использовать из-за каких-то проблем с производительностью.
В тех местах, где его стоит применять, никакого выбора нет. Там так не стоит вопрос.
Считаю, что этот вопрос нужно изучить, прежде чем отвечать.
Ну что ж, изучай.

alxt (инкогнито)
28 марта 2016, 07:03

Надо будет сохранить этот пост и давать на него ссылку при вопросе "почему PHP не подходит для production".
Простейшие для нормальных языков вещи- и делаются через ж..у.

PS: поэтому и ctrl+enter не отправяет комментарий? :D

pavelpat (инкогнито)
28 марта 2016, 07:56

"почему PHP не подходит для production".
А причём тут именно php? То, что пулер коннекшнов может кинуть вас на другой сервер, где prepared statement-а ещё нет, как-то относится к пхп?

Евгений, а почему нельзя просто использовать PgBouncer в режиме "Session pooling" для пула, а в конце каждой сессии делать DEALLOCATE подготовленного запроса? Разве это не решит проблему?

silent (инкогнито)
28 марта 2016, 08:07, ответ предназначен bolknote.ru:

pgbouncer позволяет при коннекте выполнять определенный запрос, можно запихнуть туда вызов функции, которая создаст все нужные планы

bolknote.ru (bolknote.ru)
28 марта 2016, 08:10, ответ предназначен alxt

Надо будет сохранить этот пост и давать на него ссылку при вопросе «почему PHP не подходит для production».
Простейшие для нормальных языков вещи, и делаются через ж…у.
А как в других языках это сделать? Как какая-то нибудь Java узнает куда pgpool кинул запрос?
PS: поэтому и ctrl+enter не отправяет комментарий? :D
Да ленюсь всё починить :)

bolknote.ru (bolknote.ru)
28 марта 2016, 08:11, ответ предназначен pavelpat

Евгений, а почему нельзя просто использовать PgBouncer в режиме «Session pooling» для пула, а в конце каждой сессии делать DEALLOCATE подготовленного запроса? Разве это не решит проблему?
Это убъёт всю идею кеширования планов — всё будет парситься заново.

bolknote.ru (bolknote.ru)
28 марта 2016, 08:12, ответ предназначен silent

pgbouncer позволяет при коннекте выполнять определенный запрос, можно запихнуть туда вызов функции, которая создаст все нужные планы
Как узнать какие планы нужные?

silent (инкогнито)
28 марта 2016, 08:21, ответ предназначен bolknote.ru:

всегда есть какие-то наиболее частые и сложные запросы в системе, обычно для них планы и строят

bolknote.ru (bolknote.ru)
28 марта 2016, 08:26, ответ предназначен silent

Да их сотни. И планы надо на всё строить, что с биндами.

alxt (инкогнито)
31 марта 2016, 14:30

> А как в других языках это сделать? Как какая-то нибудь Java узнает куда pgpool кинул запрос?
А зачем знать, если у меня пулл потоков, а не дохнущие одноразовые? Можно вообще не заморачиваться - будет прогрев нескоько дольше, и всё.

bolknote.ru (bolknote.ru)
31 марта 2016, 15:46, ответ предназначен alxt

Вы внимательно всё перечитайте. Разговор как раз о *не* дохнущих соединениях и о том, что приложение не знает куда pgpool кинет запрос и подготовлен он уже там или нет.

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)