Реальный бой | Позиционирование проблемы искажения данных Hive, устранение неполадок и решение

Большие данные
Реальный бой | Позиционирование проблемы искажения данных Hive, устранение неполадок и решение

Как найти, как найти и как решить наклон данных Hive


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

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

Эта статья была впервые опубликована в публичном аккаунте:Пять минут на изучение больших данных

Когда задача зависает на 99% в процессе выполнения, велика вероятность того, что есть перекос данных, но обычно наш SQL очень большой, и нам нужно определить, какой фрагмент кода вызывает перекос, чтобы помочь нам решить проблему. перекос. Взгляните на следующий очень простой примерКак найти код, который приводит к искажению данных.

описание структуры таблицы

Давайте сначала разберемся, какие поля и объемы данных нам нужно использовать в этих таблицах:

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

первая таблица: user_info (таблица информации о пользователе, детализация пользователя)

имя поля Значение поля описание поля
userkey пользовательский ключ Идентификатор пользователя
idno Идентификационный номер пользователя Получено во время аутентификации пользователя по реальному имени
phone Мобильный номер пользователя Номер мобильного телефона пользователя при регистрации
name Имя пользователя Имя пользователя

Объем данных таблицы user_info: 102 миллиона, размер: 13,9G, занятое пространство: 41,7G (три копии HDFS)

второй стол: user_active (таблица активных пользователей, степень детализации пользователей)

имя поля Значение поля описание поля
userkey пользовательский ключ Если пользователь не зарегистрирован, ему будет присвоен ключ
user_active_at Дата последней активности пользователя Получить последнюю активную дату пользователя из таблицы журнала

Количество данных в таблице user_active: 110 миллионов

третий стол:user_intend (таблица намерений пользователей, сюда берутся данные только за последние полгода, детализация пользователей)

имя поля Значение поля описание поля
phone Мобильный номер пользователя Предполагаемые пользователи должны быть зарегистрированными пользователями с номерами мобильных телефонов
intend_commodity Продукты с наибольшим количеством пользовательских намерений У клиентов больше всего намерений в отношении продукта
intend_rank Уровень намерения пользователя Уровень покупательского намерения пользователя, чем выше уровень, тем сильнее намерение

Количество данных в таблице user_intend: 8 миллионов

четвертый стол:user_order (таблица заказов пользователей, сюда берутся только данные заказов за последние полгода, гранулярность пользователя)

имя поля Значение поля описание поля
idno Идентификационный номер пользователя Пользователи, размещающие заказы, аутентифицируются под настоящими именами.
order_num Количество заказов пользователя Количество заказов, размещенных пользователями за последние шесть месяцев
order_amount Общая сумма заказа пользователя Общее количество заказов, размещенных пользователями за последние шесть месяцев.

Объем данных таблицы user_order: 6,4 млн.

1. Спрос

Требование очень простое: связать приведенные выше четыре таблицы для формирования таблицы большой ширины, которая содержит основную информацию о пользователе, статусе активности, намерении совершить покупку и статусе заказа пользователя.

2. Код

В соответствии с вышеуказанными требованиями мы используем таблицу user_info в качестве базовой таблицы, а остальные таблицы связываем в широкую таблицу.Код выглядит следующим образом:

select
  a.userkey,
  a.idno,
  a.phone,
  a.name,
  b.user_active_at,
  c.intend_commodity,
  c.intend_rank,
  d.order_num,
  d.order_amount
from user_info a
left join user_active b on a.userkey = b.userkey
left join user_intend c on a.phone = c.phone
left join user_order d on a.idno = d.idno;

Когда приведенный выше оператор выполняется, задача зависает на 99% при выполнении определенного задания:

В это время мы должны рассмотреть возникновение перекоса данных. На самом деле может быть и другая ситуация, что данные перекошены, то есть задача убита по таймауту, а объем данных, обрабатываемых Reduce, огромен. вызывает тайм-аут ответа,сверх значения по умолчанию 600 секунд, задача убита. Сообщение об ошибке обычно выглядит следующим образом:

AttemptID:attempt_1624419433039_1569885_r_000000 Timed outafter 600 secs Container killed by the ApplicationMaster. Container killed onrequest. Exit code is 143 Container exited with a non-zero exit code 143

3. Устранение проблем с наклоном

Перекос данных в основном вызван крупными ключевыми проблемами.

Как судить о проблеме, вызванной большим ключом, можно использовать следующие методы:

1. Судя по времени

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

Уведомление: Чтобы исключить два случая:

  1. Если время выполнения каждого сокращения примерно одинаково, и все они очень длинные, это не обязательно вызвано перекосом данных, но может быть вызвано слишком малым количеством настроек сокращения.

  2. Иногда может возникнуть проблема с узлом, на котором выполняется задача, из-за чего задача выполняется очень медленно. В это время спекулятивное выполнение mapreduce перезапустит задачу. Если новую задачу можно выполнить за очень короткое время, это обычно связано с проблемой узла выполнения задачи, что отдельная задача выполняется медленно. Однако, если задача выполнения задачи после спекулятивного выполнения также особенно медленная, это означает, что задача может иметь проблему перекоса.

2. Судя по счетчику задач

Счетчик будет записывать статистику всей работы и каждой задачи. URL-адрес счетчика обычно похож на:

http://bd001:8088/proxy/application_1624419433039_1569885/mapreduce/singletaskcounter/task_1624419433039_1569885_r_000000/org.apache.hadoop.mapreduce.FileSystemCounter

При вводе количества записей обычный счетчик задач выглядит следующим образом, а количество входных записей составляет более 1,3 миллиарда:

Счетчик задачи=000000 выглядит следующим образом, а количество входных записей превышает 23 миллиарда. В 100 раз больше, чем другие задачи:

4. Найдите код SQL

1. Определите этап, на котором задача зависла

  • Определить этап по имени задания:

    Как правило, имя задания по умолчанию Hive переносит этап этапа, как показано ниже, через имя задания, чтобы увидеть, что задача застряла на этапе 4:

  • Если имя задания настроено индивидуально, определить этап по имени задания может быть невозможно. Необходимо полагаться на журнал задач:

    Найдите задачу, которая особенно медленная, затем нажмите Ctrl+F для поиска «CommonJoinOperator: JOIN struct». Когда Hive присоединяется, он печатает ключ присоединения в журнале. следующее:

Ключевая информация на изображении выше:struct<_col0:string, _col1:string, _col3:string>

В это время вам нужно обратиться к плану выполнения SQL. Обращаясь к плану выполнения, можно сделать вывод, что этот этап является Этапом-4:

2. Определите код выполнения SQL

Определяется этап исполнения, то есть стадия. С помощью плана выполнения вы можете определить, какой код искажается при его выполнении. На этом рисунке псевдоним таблицы для операции соединения на этом этапе — d:

Можно сделать вывод, что существует перекос данных при выполнении кода в красном поле ниже, потому что псевдоним таблицы в этой строке — d:

5. Устранение тильта

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

Причина наклона:

В примерах данных в этой статье user_info и user_order связаны номерами идентификаторов.Обнаружено, что в таблице user_info имеется более 70 миллионов идентификаторов, которые пусты.Причина в том, что эти более 70 миллионов данных распределены по сокращение для выполнения, что приводит к перекосу данных.

Решение:

  1. Вы можете сначала удалить пустой идентификационный номер, а затем связать и, наконец, подключиться в соответствии с ключом пользователя, потому что все ключи пользователя имеют значения:
with t1 as(
select
  u.userkey,
  o.*
from user_info u
left join user_order o
on u.idno	= o.idno
where u.idno is not null
--是可以把where条件写在后面的,hive会进行谓词下推,先执行where条件在执行 left join
)

select
  a.userkey,
  a.idno,
  a.phone,
  a.name,
  b.user_active_at,
  c.intend_commodity,
  c.intend_rank,
  d.order_num,
  d.order_amount
from user_info a
left join user_active b on a.userkey = b.userkey
left join user_intend c on a.phone = c.phone
left join t1 d on a.userkey = d.userkey;
  1. Также можно присвоить случайное значение данным, у которых ID-карта пуста, но следует отметить, что случайное значение не может дублироваться с номером ID-карты в таблице:
select
  a.userkey,
  a.idno,
  a.phone,
  a.name,
  b.user_active_at,
  c.intend_commodity,
  c.intend_rank,
  d.order_num,
  d.order_amount
from user_info a
left join user_active b on a.userkey = b.userkey
left join user_intend c on a.phone = c.phone
left join user_order d on nvl(a.idno,concat(rand(),'idnumber')) = d.idno;

Другие решения для перекоса данных:

1. Отфильтруйте грязные данные

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

2. Предварительная обработка данных

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

3. Увеличьте количество редукторов

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

Настройте количество уменьшения:

set mapred.reduce.tasks = 15;

4. Преобразовать в карту

Если две таблицы объединены, и одна таблица является небольшой, для этого можно использовать mapjoin.

Настройте присоединение к карте:

set hive.auto.convert.join = true;  是否开启自动mapjoin,默认是true

set hive.mapjoin.smalltable.filesize=100000000;   mapjoin的表size大小

5. Включите оптимизацию перекоса соединения

Можно установить в улейhive.optimize.skewjoinРазделите SQL-запрос соединения на два задания. При этом можно установитьhive.skewjoin.key, этот параметр указывает, что количество строк ключа, соединенных соединением, превышает указанное количество строк, ключ считается ключом асимметричного соединения, и для объединения включена оптимизация асимметричного соединения. Количество строк ключа по умолчанию равно 100000.

Чтобы настроить оптимизацию неравномерного соединения:

set hive.optimize.skewjoin=true; 启用倾斜连接优化

set hive.skewjoin.key=200000; 超过20万行就认为该键是偏斜连接键

6. Настройте параметры памяти

Он подходит для сценариев, в которых задачи прекращаются из-за переполнения памяти. Увеличивая память, по крайней мере задача может работать и не быть убитой. Этот параметр не обязательно значительно сокращает время выполнения задачи.

Настроить память:

set mapreduce.reduce.memory.mb=5120; 设置reduce内存大小

set mapreduce.reduce.java.opts=-Xmx5000m -XX:MaxPermSize=128m;

Приложение: Официальная ссылка свойств конфигурации Hive:Из wiki.Apache.org/confluence/…