Трудности перекоса: как устранить неравномерность данных и вычислений в Greenplum

Автор Категория ,
Трудности перекоса: как устранить неравномерность данных и вычислений в Greenplum

Партиционирование таблиц – надежный способ повышения производительности Greenplum, который тесно связан с особенностями распределения данных по сегментам кластера. Читайте далее, чем опасно неравномерное распределение данных и вычислений по узлам, а также как найти дата-инженеру и устранить эти перекосы в MPP-СУБД, чтобы повысить скорость выполнения SQL-запросов и решить проблемы с нехваткой памяти на хостах.

Чем опасны перекосы в Greenplum

Для любой распределенной системы перекосы, когда на данные распределены неравномерно по узлам кластера, чревато снижением производительности за счет накладных расходов на передачу данных по сети. В массивно-параллельной системе без общего доступа к ресурсам общее время ответа на запрос измеряется временем его завершения для всех сегментов, аналогично тому как караван идет со скоростью движения самого медленного верблюда. При неравномерном распределении данных по сегментам, более загруженные инстансы PostgreSQL в кластере Greenplum (GP) требуют больше времени для завершения вычислений. Поэтому все сегменты должны иметь примерно одинаковое количество строк и выполнять примерно одинаковый объем обработки, чтобы предупредить снижение производительности и нехватки памяти на локальном узле.

Кроме перекоса данных в MPP-СУБД Greenplum возможен также перекос вычислений, который случается, если непропорционально большой объем данных поступает в один или несколько сегментов и обрабатывается только ими. Чаще всего именно по этой причине возникают проблемы с производительностью и стабильностью Greenplum, особенно при выполнении операций соединения, сортировки, агрегирования и других OLAP-запросов. Асимметрия вычислений происходит в процессе выполнения запроса, и обнаружить это сложнее, чем перекос данных, вызванный из-за неправильного выбора ключей дистрибуции. Перекос данных присутствует на уровне таблицы, поэтому его можно легко обнаружить и избежать, выбрав оптимальные ключи распределения. А перекос вычислений может привести к выходу из строя отдельных сегментов на хосте, о чем мы упоминаем здесь. Как обнаружит перекосы в данных и вычислениях, мы рассмотрим далее.

Как распределить данные по узлам кластера GP

Для оптимальной стратегии распределения данных рекомендуется учитывать следующие лучшие практики [1]:

  • явно задавать столбец или случайное распределение для всех таблиц вместо значения по умолчанию;
  • использовать один столбец в качестве ключа дистрибуции, который будет равномерно распределять данные по всем сегментам;
  • не распространять столбцы, которые будут использоваться в условии WHERE, а также не задавать в качестве ключа дистрибуции дату или метку времени (timestamp);
  • данные столбца с ключом дистрибуции должны содержать уникальные значения или очень большое количество элементов;
  • если один столбец не обеспечивает равномерное распределение, в качестве ключа дистрибуции можно использовать два столбца. Однако, дополнительные значения столбцов обычно не обеспечивают более равномерного распределения, но требуют больше времени для хеширования.
  • Если ключ дистрибуции из двух столбцов не обеспечивает равномерного распределения данных, стоит использовать случайное распределение. В Greenplum случайное распределение не является циклическим, поэтому оно не дает гарантии равного количества записей в каждом сегменте. Обычно случайные распределения попадают в целевой диапазон менее десяти процентов вариации.
  • Оптимальное распределение имеет решающее значение при объединении больших таблиц. Чтобы выполнить JOIN-соединение, совпадающие строки должны находиться в одном сегменте. Если данные не распределяются в одном столбце соединения, необходимые строки из одной из таблиц динамически перераспределяются в другие сегменты. Иногда выполняется широковещательное движение (broadcasting), при котором каждый сегмент отправляет свои отдельные строки всем другим сегментам, а перераспределяет данные, когда каждый сегмент повторно хэширует их и отправляет строки в соответствующие сегменты в соответствии с хеш-ключом.
  • хэш-распределение, которое равномерно распределяет строки таблицы по всем сегментам и приводит к локальным JOIN-соединениям, может увеличить производительность, за счет локальной обработки строк в одном сегменте. Локальные соединения сокращают перемещение данных: каждый сегмент работает независимо от других. Чтобы использовать преимущества локальных соединений для больших таблиц, их следует распределить по одним и тем же столбцам и в одном порядке. Столбцы распределения также должны иметь один и тот же тип данных.

Избежать неравномерного распределения данных поможет схема gp_toolkit с двумя представлениями, которые можно использовать для проверки перекоса [2]:

  • представление gp_skew_coefficients показывает перекос в распределении данных, вычисляя коэффициент вариации (CV, coefficient of variation) для данных, хранящихся в каждом сегменте. Столбец skccoeff показывает CV, рассчитанный как стандартное отклонение, деленное на среднее значение с учетом изменчивости ряда данных вокруг среднего значения. Чем ниже значение CV, тем лучше. Высокие значения CV указывают на больший перекос данных.
  • представление gp_skew_idle_fractions показывает перекос в распределении данных путем вычисления процента простоя системы во время сканирования таблицы. Это является индикатором перекоса вычислений, неравномерного распределения данных или перекоса обработки запросов. Например, значение столбца siffractionравное 0,1 означает перекос на 10%, 0,5 соответствует перекосу в 50% и т.д. Для таблиц с перекосом более 10% следует пересмотреть политику распространения данных по сегментам.

Перекос вычислений: найти и обезвредить

В отличие от утилит, ориентированных на поиск перекоса в данных, искать причину неравномерности вычислений придется вручную, включая определение файлов утечки. При наличии перекоса следует найти SQL-запрос, из-за которого это случилось. Для этого потребуется выполнить целый ряд шагов [1]:

  1. найти OID (Object Identifier, идентификатор объекта – строка или последовательность десятичных цифр, однозначно идентифицирующая объект) для базы данных, которая будет отслеживаться на предмет обработки искажений с помощью команды SELECT oid, datname FROM pg_database;
  2. запустить команду gpssh, чтобы проверить размеры файлов во всех узлах сегмента в системе, заменив <OID> на реальный OID базы данных.

[[email protected] kend]$ gpssh -f ~/hosts -e \

    “du -b /data[1-2]/primary/gpseg*/base/<OID>/pgsql_tmp/*” | \

    grep -v “du -b” | sort | awk -F” ” ‘{ arr[$1] = arr[$1] + $2 ; tot = tot + $2 }; END \

    { for ( i in arr ) print “Segment node” i, arr[i], “bytes (” arr[i]/(1024**3)” GB)”; \

    print “Total”, tot, “bytes (” tot/(1024**3)” GB)” }’ –

  1. При наличии значительной и устойчивой разница в использовании диска, выполняемые SQL-запросы нужно исследованы на предмет перекоса, чтобы определить некорректный запрос. Например, просмотреть фактический каталог сегментов, войдя в конкретный узел или с помощью мастера:

$ gpssh -f ~/hosts -e

    “ls -l /data[1-2]/primary/gpseg*/base/19979/pgsql_tmp/*”

    | grep -i sort | awk ‘{sub(/base.*tmp\//, “…/”, $10); print $1,$6,$10}’ | sort -k2 -n

  1. Обычно сегмент, на котором есть перекос, содержит файлы большего размера, чем другие. Войдя в узел с этим сегментом с помощью ssh и пользователя root, нужно найти процесс, вызывающий перекос. Команда lsof позволит определить PID процесса, которому принадлежит один из больших файлов:

[[email protected] ~]# lsof /data2/primary/gpseg45/base/19979/pgsql_tmp/pgsql_tmp_slice10_sort_15673_0002.1COMMAND  PID    USER    FD   TYPE DEVICE  SIZE        NODE        NAMEpostgres 15673  gpadmin 11u  REG  8,48    1073741824  64424546751 /data2/primary/gpseg45/base/19979/pgsql_tmp/pgsql_tmp_slice10_sort_15673_0002.1

В рассматриваемом примере PID равен 15673.

  1. Команда ps с PID поможет идентифицировать базу данных и информацию о соединении:

[[email protected] ~]# ps -eaf | grep 15673gpadmin  15673 27471 28 12:05 ?        00:12:59 postgres: port 40003, sbaskin bdw        172.28.12.250(21813) con699238 seg45 cmd32 slice10 MPPEXEC SELECTroot     29622 29566  0 12:50 pts/16   00:00:00 grep 15673 

  1. На мастер-хосте кластера Greenplum следует проверить лог-файл pg_log для пользователя, соединения и команды из результатов, полученных на предыдущем шаге. Строка в лог-файле с этими тремя значениями должна быть строкой, содержащей запрос, но иногда номер команды может незначительно отличаться. Например, в выходных данных ps может отображаться cmd32, но в файле журнала это cmd34. Если запрос все еще выполняется, последний запрос для пользователя и подключения являются ошибочными.

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

Узнайте больше практических деталей по работе с этой MPP-СУБД для эффективного хранения и аналитики больших данных на новом авторском курсе «Greenplum для инженеров данных» в  нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве.

Источники

  1. https://gpdb.docs.pivotal.io/6-16/best_practices/schema.html