Slide 1

Slide 1 text

Join Algorithm in Spark 2022/06/28 @yabooun

Slide 2

Slide 2 text

自己紹介 藪本 晃輔 @yabooun 株式会社ジオロジック CTO 趣味: 登山、ピアノ、日本酒 晴れてると、空ばかり眺めてしまうので、今週末山に行ってきます。

Slide 3

Slide 3 text

Joinとは ● 複数のテーブルを一定のルールに基づいて結合する処理 ● SQLの基本的な構文のひとつ ● LEFT JOIN, RIGHT JOIN, INNER JOIN, CROSS JOIN, LEFT LATERAL JOIN, ・・・ ● サブクエリも全部JOINで書ける ● ただし、同じJOINでも、データ量やクエリによって違うアルゴリズムが使われる ○ 使われるアルゴリズムは基本的に処理系が決める ○ アルゴリズムによって全然速さが違う ● RDBMSやHadoop/Spark等のビッグデータ系のシステムでは別のアルゴリズム ○ ビッグデータ系はRDBMSより多くのアルゴリズムがある ● 意外と奥が深いJOIN

Slide 4

Slide 4 text

RDBMSにおけるJOIN 1. Hash Join 2. Sort Merge Join 3. Nested Loop Join

Slide 5

Slide 5 text

Hash Join 大きいテーブルと小さいテーブルを結合するときに使う。結合条件がシンプルなA=Bのときに利用可能。 1. 小さいテーブルの結合キーでハッシュを作成 2. 大きいテーブルをスキャン 3. 1行ごとに小さいテーブルをハッシュ検索 ● 大きい方のテーブルをScanするだけなので最速 ● 一番優先されるアルゴリズム ● 片方が小さくないとHashがメモリに乗らない ● インデックスがあるとさらに高速

Slide 6

Slide 6 text

Sort Merge Join 大きいテーブル同士を結合するときに使う。結合条件がシンプルなA=Bのときに利用可能。 1. 両方テーブルをそれぞれ結合キーでソート 2. それぞれのテーブルを上から順番に読みながら、結合 結果を出力する (ソート順が若い方のテーブルのカーソルを進めながら処理し ていくイメージ) ● 大きいテーブル同士では有効 ● 結合キーにインデックスがないとソートに時間がかかる ● 複雑な結合条件に対応できない

Slide 7

Slide 7 text

Nested Loop Join Hash JoinとSort Merge Joinで対応できないときに使用 1. 片方のテーブルをScan 2. Scanしながら1行ごとにもう一方のテーブルを全部 Scan 3. 結合条件にマッチしていたら結合 ● N * N のコストがかかる ● どんな条件でもできる ● 基本的には使わせたくない

Slide 8

Slide 8 text

RDBMSにおけるJOIN ● 基本的にはHash Joinが使われるようにしよう ● せめてSort Merge Joinが使われるようにしよう ● Joinのキーはインデックス登録しておこう ● 文字列結合したり変な条件で Joinすると遅い

Slide 9

Slide 9 text

SparkにおけるJOIN ● Sparkでもほとんど似た考え方の Joinが使われる ● 複数のノードからなるクラスタで実行されるため、同じアルゴリズムでも複数パターン ● アルゴリズムひとつ変わると、クエリの速度が 1,000倍くらい余裕で変わる

Slide 10

Slide 10 text

SparkにおけるJOIN 1. Broadcast Hash Join 2. Shuffle Hash Join 3. Shuffle Sort Merge Join 4. Broadcast Nested Loop Join 5. Cartesian Join

Slide 11

Slide 11 text

Broadcast Hash Join 大きいテーブルと小さいテーブルを結合するときに使う。結合条件がシンプルなA=Bのときに利用可能。 1. 小さいテーブルの結合キーでハッシュを作成 2. ハッシュをすべてのノードにコピー 3. 各ノードでHash Join 4. 結果を結合 ● 一番早い。とにかくこれを使え。 ● Sparkの仕様上小さいテーブルが8MBまで。 (Sparkのデフォルトはたしか1MBくらいになっているこ とが多い)

Slide 12

Slide 12 text

Shuffle Hash Join 大きいテーブルとそこそこ大きいテーブルを結合するときに使う。結合条件がシンプルなA=Bのときに利用可能。 1. それぞれをテーブルを結合条件でshuffle 2. 各ノードでHash作成 3. 各ノードでHash Join 4. 結果を結合 ● Broadcast Hash Joinの次に早い ● おそらくShuffleでIOが発生するケースがあるからか、 想像より遅い

Slide 13

Slide 13 text

Shuffle Sort Merge Join 大きいテーブル同士を結合するときに使う。結合条件がシンプルなA=Bのときに利用可能。 1. それぞれをテーブルを結合条件でshuffle 2. 各ノードでSort Merge Join 3. 結果を結合 ● あまり早くない ● Shuffleが発生する上に、各ノードでソート ● Shuffle、ソートはどちらも大きなデータでは時間のかか る処理

Slide 14

Slide 14 text

Broadcast Nested Loop Join 結合条件が複雑なときに使用。両方が大きすぎると手の打ちようがない。 1. 小さいの方のテーブルを全ノードにコピー 2. 大きい方のテーブルを各ノードに分散 3. 各ノードでNested Loop Join 4. 結果を結合 ● 使ってはいけないくらい重い ● 使ったらエラーを出すオプションもある

Slide 15

Slide 15 text

JOINの敵、Skew Skewとはデータの偏り。偏りが大きいと全体の結果がなかなか返ってこない。 Shuffle系のJoinで問題になる。 このケースだと、Worker1の処理が終わるまで全体のJoinが完了しない。

Slide 16

Slide 16 text

Skewの最適化 Spark 3.0でSkew Hintを与えることにより(条件によってはHintがなくても)Skewを検知してデータを再分散し、偏りによる問題 を最小化する機能が追加された。 Skewの発生しているWorker1を再分散して別のWorkerで処理をする。

Slide 17

Slide 17 text

結論 ● できるだけBroadcast Joinを使おう ○ マスタとの結合は明示的に Bradcast Hash Joinを使わせたりする ● どうしても出来ないときでも、複雑な条件では Joinしないようにしよう ● Shuffle Joinが発生するカラムは均等に分散される設計にしよう ○ IDFAやランダムな文字列などは基本的に偏りがない ○ ステータスやtype系のものでJoinしようとするとSkewが発生しやすい ● あとは実際どのJoinが使われているか、実行プランを確認しよう