Пишу, по большей части, про историю, свою жизнь и немного про программирование.

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

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

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

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

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

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

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

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

19 комментариев
pavelpat 2016

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

Евгений Степанищев (bolknote.ru) 2016

Комментарий для pavelpat:

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

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

hshhhhh.name 2016

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

Евгений Степанищев (bolknote.ru) 2016

Комментарий для hshhhhh.name:

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

Евгений Степанищев (bolknote.ru) 2016

Комментарий для hshhhhh.name:

Я не знаю что такое планы в постгресе

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

pavelpat 2016

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

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

Олег Горбунов 2016

Комментарий для Евгения Степанищева:

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

Евгений Степанищев (bolknote.ru) 2016

Комментарий для Олег Горбунов:

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

Да, конечно!

Евгений Степанищев (bolknote.ru) 2016

Комментарий для pavelpat:

Насчёт стоимости savepoint’а, ни разу не слышал, что этот механизм не стоит использовать из-за каких-то проблем с производительностью.

В тех местах, где его стоит применять, никакого выбора нет. Там так не стоит вопрос.

Считаю, что этот вопрос нужно изучить, прежде чем отвечать.

Ну что ж, изучай.

alxt 2016

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

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

pavelpat 2016

«почему PHP не подходит для production».

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

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

silent 2016

Комментарий для Евгения Степанищева:

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

Евгений Степанищев (bolknote.ru) 2016

Комментарий для alxt:

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

А как в других языках это сделать? Как какая-то нибудь Java узнает куда pgpool кинул запрос?

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

Да ленюсь всё починить :)

Евгений Степанищев (bolknote.ru) 2016

Комментарий для pavelpat:

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

Это убъёт всю идею кеширования планов — всё будет парситься заново.

Евгений Степанищев (bolknote.ru) 2016

Комментарий для silent:

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

Как узнать какие планы нужные?

silent 2016

Комментарий для Евгения Степанищева:

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

Евгений Степанищев (bolknote.ru) 2016

Комментарий для silent:

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

alxt 2016

А как в других языках это сделать? Как какая-то нибудь Java узнает куда pgpool кинул запрос?

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

Евгений Степанищев (bolknote.ru) 2016

Комментарий для alxt:

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