Искры, оптимизация генерации показателей из DF
Это вопрос оптимизации, это моя текущая (рабочая) ситуация:
- Spark работает в автономном режиме с использованием spark-jobserver;
- У меня есть файл паркета с ~ 3M строк, кэшированных в памяти в виде таблицы;
- Таблица представляет собой совокупность всех данных с сайта электронной торговли, каждая строка представляет пользователя, но пользователь может иметь больше строк;
Клиентский запрос должен выполнять SQL-запрос и показывать результаты на веб-странице в некоторых таблицах, каждый из которых представляет метрику с помощью счетчика, например:
Возраст = > 18-20: 15 пользователей, 21-35: 42 пользователей,...
Страна = > США: 22 пользователя, GB: 0 пользователей,...
И так далее. Подсчитывая все таблицы (вместе с некоторыми сеансами пользователей, которые генерируются на основе активности, периода и года), мы имеем в настоящее время ~ 200 показателей.
Последняя выпущенная система в производстве использует (учитывая df как DataFrame в результате SQL-запроса):
df.rdd.aggregate(metricsMap) (
(acc: MetricsMap, r:Row) => {
acc.analyzeRow(r)
acc
},
(acc1: MetricsMap, acc2: MetricsMap) => {
acc1.merge(acc2)
acc1
}
)
Где MetricsMap - это объект, используемый для извлечения и агрегирования данных из строки.
Эта операция очень интенсивна для процессора, а на сервере требуется ~ 20 секунд, чтобы извлекать данные из запроса без параметров (поэтому из всех данных в файле паркета).
Я решил использовать агрегацию, потому что для их статистического анализа им нужны несколько перспектив: некоторые показатели должны подсчитываться с помощью ключа пользователя, другого по имени пользователя (для сайта...), а другое - по ключу продукта. Используя этот метод, мне пришлось циклически перебирать результат только один раз, но я не знаю, подходит ли ему лучший подход...
Это лучший подход или существует какой-то другой (более быстрый) метод для получения того же результата?
Что касается вопроса о вычислении метрик заранее, запросы, которые они могут делать в наборе данных, не связаны, поэтому я не знаю, возможно ли это или нет... Не могли бы вы привести пример?
Отвечая на некоторые вопросы
Ответы
Ответ 1
Один путь данных в таких случаях, очевидно, лучше, чем несколько циклов, в случаях, когда вы хотите ответить на несколько запросов для одного и того же запроса.
Может быть более эффективным, хотя и не взаимодействовать с искровым сердечником.
Например, если ваша схема DF выглядит следующим образом:
root
-- age
-- country
Затем вы можете попытаться выполнить следующий псевдо-базовый запрос:
Select
CASE WHEN (age BETWEEN 18 AND 22) THEN '18-22'
WHEN (age BETWEEN 22 AND 30) THEN '22-30'
ELSE 'Other' as age_group,
country
from metrics_df
Вы также можете рассмотреть возможность использования UDF для возрастной группы.
Как упомянуто в @assaf-mendelson, здесь больше информации.