🐘 Подготовленные планы в PostgreSQL
Но вот какая неприятность — при подключении любого балансировщика нагрузки, совершенно неочевидно куда улетает ваш план и таблица в приложении не помогает — она единая, а серверов может быть несколько, у каждого свои планы подготовленные. Если мы начнём подготавливать его заново, а он уже есть, получим ошибку, что план уже существует.
Какой выход? Краткий ответ: пока никакой.
Самый очевидный — игнорировать такие ошибки. К сожалению, он не подойдёт — если ошибка произойдёт в транзакции, «Постгрес» её просто откатит. Второй выход — не использовать подготовленные планы. Я пока нашёл третий — мы используем планы только если уверены, что они пойдут на мастер — это запросы на изменение
С другой стороны у меня появилась идея — добавить в эскуэль конструкцию PREPARE IF NOT EXISTS, ребята из, с которыми я обсуждал эту идею, PostgresPro уже сделали несколько версий патча.
Основа идеи — всегда слать запрос на компиляцию плана, но если он уже был скомпилирован, ничего не делать. Мы его уже погоняли (оттуда и цифры первого абзаца), но на этом пути больше трудностей, чем себе можно представить — в частности, надо патчить ещё и продукты для балансировки и расширять его клиентский протокол.
Очень надеюсь, что патч доведут до ума и мы скоро сможем его использовать.
Комментарии 19
Планы в «Постгресе» то же, что и в любой другой базе.
Не могу ответить однозначно, но думаю, что данные попадают на реплики только после коммита всей транзакции, а savepoint на этот механизм никак не влияет.из-за каких-то проблем с производительностью. Считаю, что этот вопрос нужно изучить, прежде чем отвечать.
Насчёт стоимости savepoint'а, ниразу не слышал, что этот механизм не стоит использовать
Обидно еще то, как я понимаю, подготовленный план гораздо выгоднее в сложных селектах?
Да, конечно!
Комментарий для pavelpat:
В тех местах, где его стоит применять, никакого выбора нет. Там так не стоит вопрос.
Ну что ж, изучай.
Простейшие для нормальных языков вещи- и делаются через ж..у.
PS: поэтому и ctrl+enter не отправяет комментарий? :D
А как в других языках это сделать? Каккакая-то нибудь Java узнает куда pgpool кинул запрос?
Да ленюсь всё починить :)
А причём тут именно php? То, что пулер коннекшнов может кинуть вас на другой сервер, где preparedstatement-а ещё нет, как-то относится к пхп?
Евгений, а почему нельзя просто использовать PgBouncer в режиме «Session pooling» для пула, а в конце каждой сессии делать DEALLOCATE подготовленного запроса? Разве это не решит проблему?
pgbouncer позволяет при коннекте выполнять определенный запрос, можно запихнуть туда вызов функции, которая создаст все нужные планы
Как узнать какие планы нужные?
Комментарий для pavelpat:
Это убъёт всю идею кеширования планов — всё будет парситься заново.
всегда есть
Да их сотни. И планы надо на всё строить, что с биндами.
А зачем знать, если у меня пулл потоков, а не дохнущие одноразовые? Можно вообще не заморачиваться — будет прогрев нескоько дольше, и всё.
Вы внимательно всё перечитайте. Разговор как раз о не дохнущих соединениях и о том, что приложение не знает куда pgpool кинет запрос и подготовлен он уже там или нет.