Оптимизирующий запрос spark sql - PullRequest
0 голосов
/ 12 марта 2020

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

query = """SELECT
DISTINCT NAME,
PERIODICITY,
PERCENTILE(CAST(AMOUNT AS INT), 0.997) OVER(PARTITION BY NAME, PERIODICITY) as OUTLIER_UPPER_THRESHOLD,
CASE
WHEN PERIODICITY = "WEEKLY" THEN 100
WHEN PERIODICITY = "BI_WEEKLY" THEN 200
WHEN PERIODICITY = "MONTHLY" THEN 250
WHEN PERIODICITY = "BI_MONTHLY" THEN 400
WHEN PERIODICITY = "QUARTERLY" THEN 900
ELSE 0
END AS OUTLIER_LOWER_THRESHOLD
FROM base"""

Ответы [ 2 ]

1 голос
/ 12 марта 2020

Я бы предложил перефразировать это, чтобы вы могли отфильтровать перед агрегацией:

SELECT NAME, PERIODICITY, OUTLIER_LOWER_THRESHOLD,
       MIN(AMOUNT)
FROM (SELECT NAME, PERIODICITY,
             RANK() OVER (PARTITION BY NAME, PERIODICITY ORDER BY AMOUNT) as sequm,
             COUNT(*) OVER (PARTITION BY NAME, PERIODICITY) as cnt,
             (CASE . . .  END) as OUTLIER_LOWER_THRESHOLD
      FROM base
     ) b
WHERE seqnum >= 0.997 * cnt
GROUP BY NAME, PERIODICITY, OUTLIER_LOWER_THRESHOLD;

Примечание: Это ранжирует повторяющиеся суммы на основе наименьшего ранга. Это означает, что некоторые пары NAME / PERIODICITY могут не быть в результатах. Их можно легко добавить обратно, используя LEFT JOIN.

0 голосов
/ 12 марта 2020

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

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

Если первые два подхода по какой-то причине неприменимы, пришло время провести рефакторинг. В вашем случае вы делаете два шаффла: сначала для вычисления OUTLIER_UPPER_THRESHOLD, которое вы связываете с каждой строкой, а затем для различения строк. Другими словами, вы делаете двухфазную инструкцию GROUP BY. Почему бы вам просто не сгруппировать по ИМЯ, ПЕРИОДИЧНОСТЬ и вычислить процентиль?

...