2016-06-22 10 views
0

У меня огромный SQL-запрос. Вероятно, это было 15-20 таблиц. Есть 6-7 подзапросов, которые снова соединяются. Этот запрос в большинстве случаев занимает минуту, чтобы запустить и вернуть 5 миллионов записей.Postgres Query Plan продолжает меняться - делает запрос в минуту, чтобы иногда заканчивать и никогда не заканчивается иногда

Так что даже если этот запрос плохо написан, у него есть план запросов, который заставляет его закончить через минуту. Я гарантировал, что запрос действительно выполнялся и не использовал кешированные результаты.

Иногда план запроса поднимается, а затем он не заканчивается. Каждый вечер я запускаю вакуумный анализ на таблицах, участвующих в запросе. В настоящее время work_memory установлен на 200 МБ. Я попытался увеличить это до 2 ГБ. Я не испытал, что запрос запутался, когда work_memory составлял 2 ГБ. Но когда я уменьшил его и запустил запрос, он запутался. Теперь, когда я увеличил его до 2 ГБ, запрос все еще запутан. Это что-то связано с тем, что план запроса не обновляется с новой настройкой? Я попытался отказаться от плана на моей сессии.

Я могу только думать о work_mem и анализе вакуума на этом этапе. Любые другие факторы, которые могут повлиять на плавно выполняемый запрос, который возвращает результаты за минуту, чтобы пойти и ничего не вернуть?

Дайте мне знать, если вам нужна дополнительная информация о любых настройках? или сам запрос? Я также могу вставить план тоже ... Но запрос и план или слишком большой, чтобы вставлять здесь.

+0

15-20 столов в таблице диапазонов: генетический оптимизатор будет входить. Либо увеличьте geqo_limit, либо поместите часть своей таблицы в CTE. Если у вас уже есть некоторые подзапросы, продвиньте еще один из них в CTE. – wildplasser

+0

oops, имя 'geqo_threshold'. его значение по умолчанию равно 12. Установка слишком высокой (20, вероятно, слишком высокая ...) заставит планировщика потребоваться ** много времени ** для оценки всех планов. (количество планов в основном экспоненциально зависит от количества RTE) – wildplasser

ответ

0

Если в таблице диапазонов содержится более geqo_treshold (обычно 12) записей, генетический оптимизатор будет пинать , часто приводящее к случайным поведением, как описано в вопросе. Вы можете решить эту проблему:

  • увеличивающейся geqo_limit
  • переместить некоторые из табличного referencess в КТР. Если у вас уже есть некоторые подзапросы, продвиньте один (или более) из них в CTE. Это своего рода черное искусство для определения кластеров таблиц в вашем запросе, которые будут соответствовать компактному CTE (с относительно небольшим количеством исходных кортежей и не слишком много ключевых ссылок на внешний запрос).

Установка geqo_treshold слишком высокая (20, вероятно, слишком высокая ...) заставит планировщика потребоваться много времени, чтобы оценить все планы. (количество планов увеличивается в основном экспоненциально по количеству RTE). Если вы ожидаете вашего запроса, чтобы потребоваться несколько минут для запуска, несколько секунд времени планирования, вероятно, не повредят.

+0

Прочитал некоторые настройки GEQO. Я почти уверен, что моя проблема здесь. Мой запрос слишком длинный и сложный для создания исчерпывающего плана поиска. Эвристический поиск на основе GECO не дает лучшего плана. Я немного подкорректирую параметр geqo_effort и разбиваю повторяющиеся части в моем запросе на CTE – Ramanan

+0

. Но знаете ли вы, как каждый раз, когда мой план запроса запутывается, анализ вакуума во всей базе данных устраняет проблему. Может ли GEQO сделать лучший план после анализа вакуума? – Ramanan

+0

Это просто случайность и совпадение и эвристика, я не хочу знать. Возможно, у вас есть инкрементные ключи или даже просчет статистики ...Как только geqo даст кластер связанных таблиц, варианты с использованием этого кластера, вероятно, будут преобладать. (выиграть эволюцию). Мой совет: просто отделите часть запроса (solid subquery) в CTE. – wildplasser