Как улучшить SQL запрос в Spark при обновлении таблицы? («НЕ В» в подзапросе) - PullRequest
0 голосов
/ 21 января 2020

У меня есть Dataframe в Spark, который зарегистрирован как таблица с именем A и имеет 1 billion записей и 10 столбцов. Первый столбец (ID) - это первичный ключ.

Также имеется другой Dataframe, который зарегистрирован как таблица с именем B и имеет 10,000 записей и 10 столбцов (те же столбцы, что и в таблице A, первый столбец (ID) является первичным ключом).

Записи в таблице B являются «Обновлять записи». Поэтому мне нужно обновить все 10000 записей в таблице A с записями в таблице B.

Сначала я попытался выполнить этот запрос SQL:

select * from A where ID not in (select ID from B), а затем объединить его с таблицей B .

Подход в порядке, но первый запрос (select * from A where ID not in (select ID from B)) чрезвычайно медленный (часы на умеренном кластере).

Затем я попытался ускорить первый запрос с помощью LEFT JOIN:
select A.* from A left join B on (A.ID = B.ID ) where B.ID is null

Этот подход логично выглядит логично, но он занимает ПУТЬ много памяти для контейнеров Spark
(YARN for exceeding memory limits. 5.6 GB of 5.5 GB physical memory used. Consider boosting spark.yarn.executor.memory) ..

Что было бы лучше / быстрее / меньше потребляет память подход?

1 Ответ

1 голос
/ 22 января 2020

Я бы go с left join тоже, а не not in.

Несколько советов по снижению требований к памяти и производительности -

  1. Обратите внимание, что большая таблица равномерно распределена по ключу соединения (ID). Если нет, то некоторые задачи будут сильно обременены, а некоторые слегка заняты. Это вызовет серьезную медлительность. Пожалуйста, сделайте groupBy ID and count, чтобы измерить это.
  2. Если ключ соединения естественно перекошен, то добавьте больше столбцов к условию соединения, оставив результат таким же. Большее количество столбцов может повысить вероятность равномерного перемешивания данных. Этого немного сложно достичь.
  3. Потребность в памяти зависит от - количества запущенных параллельных задач, объема данных на задачу, выполняемую в исполнителе. Уменьшение одного или обоих уменьшит нагрузку на память и, очевидно, будет работать медленнее, но это лучше, чем сбой. Я бы уменьшил объем данных для каждой задачи, создав больше разделов в данных. Допустим, у вас есть 10 разделов для строк 1B, а затем установите 200 для уменьшения объема на задачу. Используйте repartition в таблице A. Не создавайте слишком много разделов, потому что это приведет к неэффективности, разделы 10K могут быть плохой идеей.
  4. Есть некоторые параметры, которые нужно настроить, что объяснено здесь .
  5. Небольшая таблица, содержащая 10К строк, должна автоматически транслироваться, потому что она маленькая. Если нет, вы можете увеличить лимит вещания и применить подсказку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...