Greenplum
October 20

Greenplum. План запроса. Рекомендации по оптимизации (draft). 

Решил законспектировать основные вещи по сабжу из пары учебных курсов.

Перед тем, как смотреть план запроса, стоит посмотреть на сам запрос. Возможно, в глаза сразу бросится код, который выглядит подозрительно неоптимальным. Например, бывает, что остаются отладочные артефакты в коде, типа сортировки в подзапросах (order by). Или ошибочный union вместо union all. Или distinct по большому количеству полей. Соединения таблиц по условию неравенства или OR на ключи join. Проход таблицы более 1 раза на ровном месте (мне такие запросы аналитики регулярно подкидывают, причём разные люди, как по шаблону пишут). И тд и тп.

На что обратить внимание в плане запроса:

  • Узлы с наибольшей добавочной стоимостью
  • Узлы с наибольшим временем выполнения (при explain analyze)
  • Большое количество возвращаемых строк на сегмент
  • Nested Loop join при большом количестве строк
  • Hash join при небольшом количестве строк
  • Отсутствие Partition Selector при обращении к партиционированной таблице
  • Операторы Redistribute Motion, Broadcast Motion (Появление Redistribute или Broadcast Motion перед операторами соединения значит, что ключ распределения таблицы не совпадает с ключом join. Иногда это говорит о неоптимальной физической модели данных). Оператор Gather Motion, появившийся в середине плана (Это значит, что данные со всех сегментов обрабатываются на мастере, который значительно уступает по производительности множеству сегментов кластера. В норме Gather Motion появляется только в самом конце запроса (наверху плана) для вывода результатов запроса через мастер клиенту).
  • Наличие факта создания спилл-файлов (в выводе команды EXPLAIN ANALYZE один или несколько слайсов запроса отмечены звёздочкой, например * (slice1))
  • rows=1 в операторах Seq Scan, Dynamic Seq Scan, Index Scan и Bitmap Heap Scan
  • Несколько Seq Scan одной таблицы (Seq Scan on my_table ... Seq Scan on my_table my_table_1 и тп)

Планировщик может построить неоптимальное дерево плана запроса по разным причинам:

  • Отсутствующая или неактуальная статистика, из-за которой планировщик неверно оценивает стоимость плана.
  • Неоптимальная физическая модель данных, из-за которой планировщику приходится добавлять тяжёлые операторы Redistribute / Broadcast Motion и неэффективно читать данные из таблиц.
  • Сам SQL-запрос, в котором логика получения результата может быть слишком сложной: планировщик не может упростить логику самостоятельно и выбирает среди заведомо неоптимальных вариантов.

Как можно ускорить тяжёлый запрос? Или переписать сам запрос, или оптимизация окружения выполнения запроса. Или и то, и то.

По рефакторингу запроса это скорее магия, чем последовательность чётких инструкций. А по второму варианту - это актуализация статистики, изменение физической модели и, возможно, изменение типа планировщика.

Изменение физической модели это, например, разбиение сложного запроса с большим количеством джойнов на несколько, с последующей материализацией промежуточных результатов в таблицы. И в финале собрать исходный запрос уже с этими таблицами.