Длинные линейные запросы в Spark к графу, хранящемуся в таблицах Hive - PullRequest
0 голосов
/ 22 января 2020

Предположим, у меня есть граф G и следующий запрос:

     x     y     z     w     q     r    s
(?a)--(?b)--(?c)--(?d)--(?e)--(?f)--(?g)--(?h)

, где {? A,? B,? c, ...,? H} переменные, и {x, y, z, w, q, r, s} являются метками ar c.

На уровне хранения у меня есть одна таблица для каждой метки, но также для комбинации двух меток. Например, у меня может быть таблица x со столбцами | a | b | , но у меня также есть таблица xy со столбцами | a | б | с | . Да, у меня есть избыточные таблицы.

Основываясь на этом параметре, у меня есть две проблемы:

a) Мне нужно найти таблицы таким образом, чтобы соединение между ними приводило к наилучшему времени выполнения ( маленький). Пусть {xy zw, q, rs} будут этими таблицами для примера выше.

b) Мне нужно выполнить соединения в заданном порядке, поэтому мне нужно найти этот порядок, например: ( rs ⨝ q) ⨝ (zw ⨝ xy) (⨝ - естественное объединение).

Предполагая, что я знаю, какие таблицы использовать, т.е. что я решил a), мой вопрос заключается в том, как решить второй. Spark API позволяет мне выполнять все объединения в одной строке:

val res1 = xy.join(zw, Seq("c")).join(q, Seq("e")).join(rs, Seq("f"))

, но я также могу выполнить это в несколько строк:

val tmp1 = xy.join(zw, Seq("c"))

val tmp2 = q.join(rs, Seq("f"))

val res2 = tmp1.join(tmp2, Seq("e"))

Время выполнения res1.count и res2.count (средний из нескольких прогонов) отличается в моих экспериментах. Кажется, способ построения дерева влияет на выполнение.

1) Какую стратегию я могу использовать для построения дерева, которое приводит к оптимальному времени выполнения в Spark?

2 ) Если каждое отдельное дерево приводит к разной производительности, какова роль оптимизатора запросов? порядок объединения. Кажется, он ничего не делает, особенно в случае, когда у меня есть все объединения в одной строке кода:

val res1 = xy.join(zw, Seq("c")).join(q, Seq("e")).join(rs, Seq("f"))

и

val res3 = rs.join(q, Seq("f")).join(zw, Seq("e")).join(xy, Seq("c"))

В одном случае я мог иметь разумный время исполнения. В другой тайм-аут. Catalyst ничего не делает?

1 Ответ

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

Spark API позволяет мне выполнять все объединения в одной строке:

, но я также могу выполнить это в несколько строк:

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

1) Какую стратегию я могу использовать для построения дерева, которое приводит к оптимальному времени выполнения в Spark?

Это цель так называемого Catalyst Optimizer (не вы). Возможно, вы захотите изучить CostBasedJoinReorder логическую оптимизацию и JoinSelection стратегию планирования выполнения, отвечающую за обеспечение максимальной производительности соединений.

JoinSelection выполнение SparkPlanner использует стратегию планирования для планирования логического оператора Join для одного из поддерживаемых физических операторов объединения.

CostBasedJoinReorder - логическая оптимизация для изменения порядка соединений в оптимизации на основе затрат.

Если размер таблиц имеет значение, рассмотрите оптимизацию на основе затрат (CBO). Вы должны увидеть разницу. Вы должны использовать таблицы (не любые отношения) и выполнить команду ANALYZE TABLE COMPUTE STATISTICS для статистики.

Разве Catalyst ничего не делает?

Это должно оптимизировать соединения. Объясните планы запросов для получения более подробной информации.

...