データマネジメントチームの冨田 恭平です。
今回はSQLのパフォーマンスチューニングについてご紹介いたします。まず、Hiveについては時間がかかってもいつかは処理が終わる、Prestoについては「メモリ」という制約があり、処理負荷が高い場合はエラーとなってしまうという違いがあります。この記事ではprestoの実行ログの見方や、チューニングポイントについて説明させていいただくので、参考にしていただければ幸いです。
Outputログの見方について
Prestoの実行ログは大きく4つの要素で構成されています。パフォーマンスチューニングの前に、実行したSQLがどのように処理されているか、を把握できるようになることが必要です。
- 実行するクエリが最初に表示される
- Fragmentという項目でSQLの処理が分割される
- Fragment単位で進捗が表示される
where句でtimeカラムを指定していない場合はwarningが表示される
具体的なケース
例えば以下のクエリを実行した場合の実行ログについて説明いたします。サンプルとして使うクエリは、trs_td_sessionというテーブルに対して集計を行うサブクエリ2つ、そのサブクエリをjoinするクエリという構成になっています。
with pv_count_7days as ( -- ID単位で直近7日間のPV数を集計 select td_uid , count(1) as pv_7days from trs_td_session where td_interval(time, '-7d', 'jst') group by td_uid ) , latest_access as ( -- ID単位で最後のセッション日時を取得 select td_uid , td_time_string(max(start_time), 's!', 'jst') as latest_session_time from trs_td_session group by td_uid ) -- ID単位でセッションIDとサブクエリで作成したデータを結合したデータを作成 select t1.td_uid , t1.td_session_id , t2.pv_7days , t3.latest_session_time from trs_td_session as t1 inner join pv_count_7days as t2 on t1.td_uid = t2.td_uid inner join latest_access as t3 on t1.td_uid = t3.td_uid where t1.row_num = 1 limit 300
このクエリを実行すると、実行ログのFragmentは以下のようになります。最小に表示されるQuery Planを見て把握する方法もあるのですが、以下図とSQLとを照らし合わせて把握する方が手軽なのでおすすめです。
実施に対応関係を把握するとこのような形になります。
クエリチューニングの際に見るべきポイント
実行ログについて主に確認するのは以下の4点です。
- memory: 現在使用しているメモリ
- peak memory: 使用メモリの最大値
- rows/bytes: 処理したレコード数/データサイズ
- done/total: Fragment単位の分割数と進捗
ご契約のプランによって使用可能なメモリは異なるので、エラーとなる基準は変わるのですが、「Exceeded max (local) memory xxGB error.」というエラーが出た場合は負荷を下げるための調整が必要です。
エラーが出てしまった場合はどこの処理が高負荷だったかを特定し、負荷を下げるためのSQL修正を行います。メモリ使用量の多い処理は以下のドキュメントにまとまっていますので、合わせてご確認ください。
パフォーマンスチューニングについてはケースバイケースであることが多いものの、こうした実行ログの読み解き方を覚える、SQL作成時にメモリ使用量が多い/少ない処理を意識する、といった工夫でチューニングが必要になる機会を減らすことが可能です。
今回の記事は以上です。少しでも使えそうと感じていただけたら是非試してみてください。