ablog

不器用で落着きのない技術者のメモ

シンプルでシステマチックな Amazon Redshift クエリチューニング

クエリのボトルネック分析の流れ

  • STL_WLM_QUERY でクエリのキュー待ち時間と実行時間を確認する。
    • 子クエリに分割されている場合は子クエリ別に確認できる。
  • SVL_QUERY_METRICS でクエリの実行時間の内訳と仕事量(CPU時間、IO量、中間結果の書出しサイズ)を確認する。
  • SVL_QUERY_SUMMARY でクエリのボトルネックを大枠で分析する。
  • SVL_QUERY_REPORT でクエリのボトルネックの詳細を分析する。
  • その他
    • SVV_TABLE_INFO
      • アクセステーブルでソートされていないテーブルがないか確認する。
      • ソートキーが圧縮されていないか確認する。
      • アクセステーブルで統計情報が収集されてないものがないか確認する。
      • アクセステーブルでKEY分散でレコードが均等分散していないテーブルがないか確認する。
    • PG_TABLE_DEF
      • フィルタ条件に使われているカラムがソートキーに指定されているか確認する。
      • 圧縮エンコーディングされているソートキーがないか確認する。

各システムテーブル・システムビューの見方

STL_WLM_QUERY
  • キュー待ち時間:queue_start_time がキュー待ち開始時刻、queue_end_time がキュー待ち終了時刻。total_queue_time がキュー待ち時間。
  • 実行時間:exec_start_time が実行開始時刻、exec_end_time が実行終了時刻。total_exec_time が実行時間。
  • slot_count がクエリの実行に使われたスロット数。クエリにスロットを2以上割り当てている場合は、想定通りのスロット数か確認する。
  • service_class_name はクエリが実行されたワークロードキュー。想定通りのワークロードキューで実行されているか確認する。
  • query_priority はクエリが実行された際の優先度。想定通りの優先度で実行されているか確認する。
  • final_state が Completed のクエリは正常終了している。
SVL_QUERY_SUMMARY
  • stm、seg、step で昇順ソートし、上から順に処理が実行されている。
  • maxtime が大きいとそのステップがボトルネック(時間を要している)になっている可能性がある。
  • maxtime と avgtime に差がある場合、均等に並列処理されておらず、効率よく並列処理が行われていない。
  • ソートなどに使用されたメモリサイズが workmem が、メモリだけでは収まらずストレージを使用すると is_diskbased が t(rue) になる。ストレージを使用したサイズは SVL_QUERY_METRICS の query_temp_blocks_to_disk で確認する。
  • rows_pre_filter が rows より大きい場合、無駄にストレージからデータを読んでいる。
  • is_rrscan が t(rue) になっていると、ゾーンマップを使って範囲スキャンができている(ソートキーの効果は判断できない)。
SVL_QUERY_REPORT

SVL_QUERY_SUMMARY よりさらに詳細。

  • slice 、segment 、step で昇順ソートし、スライス別に上から順に処理が実行されている。
  • start_time が開始時刻 、end_time が終了時刻で、end_time - start_time が実行時間。実行時間が長いステップがボトルネック(時間を要している)になっている箇所。
  • start_time - end_time がオーバラップしている処理はが、被っていないステップは直列で実行されており、直列実行されている範囲で時間を要している範囲がボトルネックになっている。
  • 同じステップをスライス別に見たときに、rows や bytes が特定のスライスに偏っている場合は効率よく並列分散処理されていない。
  • workmem、is_diskbased、rows、rows_pre_filter、is_rrscan の見方は SVL_QUERY_SUMMARY と同じ。
SVL_QUERY_METRICS
  • query_temp_blocks_to_disk(MB) がクエリの中間結果をストレージに書き出したサイズ。SVL_QUERY_SUMMARY や SVL_QUERY_REPORT の is_diskbased = t(rue) の場合、query_temp_blocks_to_disk でサイズを確認する。
STL_EXPLAIN
  • nodeid、parentid で昇順ソートする。
  • plannode
    • cost はあくまで見積・予測のため、参考程度に見る。数値が大きくなっている箇所がボトルネックの可能性がある。
    • 非効率なオペレーションがないか確認する。
  • 以下のメッセージが出ている場合は統計情報を収集する。
 ----- Tables missing statistics: <table name> -----                                                                                                                                                                                                                                                                                                                                                                
 ----- Update statistics by running the ANALYZE command on these tables -----                                                                                                                                                                                                                                                                                                                                     
  • 以下のメッセージが出ている場合は不要な直積が発生していないかクエリを確認する。
 ----- Nested Loop Join in the query plan - review the join predicates to avoid Cartesian products -----           
SVV_TABLE_INFO
  • レコードが入っていないテーブルは SVV_TABLE_INFO に表示されない。
  • unsorted が 0 より大きいテーブルは VACCUM する。
  • テーブルにソートキーがない場合は unsorted、vacuum_sort_benefit が null になる。
  • tbl_rows、size(MB) が小さいテーブルは分散スタイルを ALL 分散にすることを検討する。
  • sortkey1_enc が none でない場合は第一ソートキーが圧縮エンコーディングされている(ソートキーは圧縮エンコーディングしないほうがよい)。
  • stats_off が 0 でないテーブルは統計情報を収集(ANALYZE)する。
  • diststyle が KEY で skew_rows が大きい場合は均等分散していないので、分散キーの変更を検討する。