昨日のImpala Cookbookの非公式日本語版の続きです。昨日は「Impalaの物理設計とスキーマ設計」でした。本日は「Impalaのメモリ使用量」です。
例によって駆け足で日本語化してるので、間違いがあればコメントに書き込むかTwitterでメンションしてください。
原文:
[1] The Impala Cookbook http://www.slideshare.net/cloudera/the-impala-cookbook-42530186
メモリ使用量 - 基本
- メモリ以下により使用される
- Hash Join - 復元(decompression)、フィルタリング、射影 (projection)後のRHSテーブル
- Group by - グループ数に比例
- Parquetの書き込みバッファ - パーティションごとに1GB
- IOバッファ (クエリに渡って共有される)
- メタデータのキャッシュ(incremental statsが使用されるときを除き、一般的にわずか1GB)
- メモリは後続のクエリのために保持、再利用される
- Impalaはver1.4以降にて、時々メモリを解放する
メモリ使用量 - メモリ使用量を見積もる
- 実行計画を使用する
- 統計情報を必要とする! 統計なしでのメモリ見積もりは無意味
- このクラスタのサイズ用にホストごとのメモリ要求をレポートする
- クラスタのサイズ変更をした場合は再実行する
- +---------------------------------------------------
+ Exlpain String
+---------------------------------------------------
+ Estimated Per-Host Requirements: Memory=26.51MB VCores=2
|
| 07:AGGREGATE [MERGE FINALIZE]
| | output: sum(count(*))
| |
- +---------------------------------------------------
- クラスタのサイズ変更をした場合は再実行する
メモリ使用量 - メモリ使用量を見積もる(続き)
- EXPLAINでのメモリ見積もりでの問題
- 見当違いになることがある - もっと多く、あるいはもっと少なく
- group byの見積もりは、かなり外れることがある - 非常に多くの列での group by の場合
- メモリ見積り=NDV of group by clolumn 1 * NDV of group by column 2 * .... NDV of group by column n
- これが非常に高い場合、EXPLAINの見積りは無視する!
- group by用に貴方自身の見積りを行う
- GROUP BYのメモリ使用量 = (グループの合計数 * 各行のサイズ) + (グループの合計数 * 各行のサイズ) / ノード数
メモリ使用量 - 実際のメモリ使用量を見つける
- プロファイルにある"Per Node Peak Memory Usage" を探す
- これは正確。プロダクション環境のキャパシティ計画にはこれを使用する
メモリ使用量 - 実際のメモリ使用量を見つける(続き)
- 複雑なクエリで、どのようにしてクエリのどの部分がとても多くのメモリを使っているのか知るのか?
- クエリプロファイルのExecSummaryを使用する!
- (図は省略。原文を参照して下さい)
メモリ使用量 - メモリ制限(Mem-limit)にヒットしている
- 単一のクエリを実行しているときでさえ、メモリ制限にヒットする上位の原因
- 1. 統計情報の不足
- 2. 単一クエリでの多くのジョイン
- 3. 大きなテーブルと大きなテーブルのジョイン
- 4. 膨大な group by
メモリ使用量 - メモリ制限(Mem-limit)にヒットしている(続き)
- 単一クエリでの多くのジョイン
- select ... from fact, dim1, dim2, dim3, ....dimN where ...
- 各 dim テーブルはメモリに合っているが、全てを合わせてではなかった
- Impala 1.4 では、Impalaは誤った計画 - BROADCAST - を選択するかもしれない
- 修正1: シャッフルのヒントを使用する
- Select ... from fact join [shuffle] dim1 on ... join dim2 [shuffle]...
- 修正2: (可能であれば)dimテーブルを事前ジョインする
- 少ないジョイン => 良好な性能!
メモリ使用量 - メモリ制限(Mem-limit)にヒットしている(続き)
- 大きなテーブルと大きなテーブルのジョイン
- (圧縮からの復元、フィルタリング、射影後)の大きなテーブルとは、クラスタの合計メモリサイズよりも大きなテーブル
- Impala 2.0は(ディスクベースのジョインにより)これを行う。差し当たって、Hiveの使用も検討する
- (高度)単純なクエリには、この高度なワークアラウンド、per-pertition join 、を試してみることができる
- 結合キーの一部になるパーティションキーが必要
- Select ... from BigTbl_A a join BigTbl_B b where a.part_key = b.part_key and a.part_key in (1,2,3)
union all
Select ... from BigTbl_A a join BigTbl_B b where a.part_key = b.part_key and a.part_key in (4,5,6)
- Select ... from BigTbl_A a join BigTbl_B b where a.part_key = b.part_key and a.part_key in (1,2,3)
- 結合キーの一部になるパーティションキーが必要
メモリ使用量 - ディスクベースのジョイン/集約
- ディスクベースのジョイン/集約は、メモリ制限にヒットしたときの最終手段にすべき
- クエリ内にひとつだけのジョイン/集約がある場合、ディスクベースのジョイン/集約を当てにする。例:
- Good: select a.*, b.* from a,b where a.id=b.id
- Good: select a.id, a.timestamp, count(*) from group by a.id, a.timestamp
- OK: select large_tbl.id, count(*) from large_tbl join tiny_tbl on (id) group by id
- Bad: select t1.id, count(*) form large_tbl_1 t1, large_tbl_2 t2 where t1.id=t2.id group by t1.id
- Bad: select a.*, b.*, c.* from a,b, c where a.id=b.id and b.col1=c.col2;
- ディスクベースのジョイン/集約を使用する際は、常にクエリごとのメモリ制限(最低2GB)をセットする
メモリ使用量 - 追記
- 見積りのために実行計画を使用する: 正確な計測にはプロファイルを使用する
- データスキュー(skew)は一様でないメモリ使用量になりうる
- メモリ不足(out of memory)の過去の一般的な問題をレビューする
- Impala 2.0以降でのディスクベースのジョインでさえ、クエリの高速化と効率的なメモリの使用のためにこれらの手順をレビューした方が良い
コメント
[…] 昨日のImpala Cookbookの非公式日本語版の続きです。昨日は「Impalaのメモリ使用量」でした。本日は「クラスタのサイジングと推奨ハードウェア」です。 […]