Amazon Redshift でディスク使用率が高くなるか、またはいっぱいになる問題をトラブルシューティングするにはどうすればよいですか?

所要時間3分
0

Amazon Redshift のディスク使用率が高くなったり、いっぱいになったりしており、この問題をトラブルシューティングしたいと考えています。

解決方法

ディスク使用率が高いエラーは、次のような要因によって変わります。

  • 分散キーとソートキー
  • クエリ処理
  • VARCHAR (MAX) 列を含むテーブル
  • 列の高圧縮
  • メンテナンスオペレーション
  • クロス結合を持つデカルト積
  • 最小テーブルサイズ
  • 廃棄ブロック
  • 大きなファイルのコピー

分散キーとソートキー

テーブルの分散スタイル、分散キー、ソートキーの選択を確認します。分散スキューのあるテーブル (あるノードに他のノードよりも多くのデータがある) があると、ディスクノードがいっぱいになる可能性があります。スキュー分散スタイルを持つテーブルがある場合は、より均一な分散に分散スタイルを変更します。分散と行スキューは、クエリの実行中に、ストレージスキューと中間行セットに影響を及ぼす可能性があることに注意してください。分散キーとソートキーの詳細については、「Amazon Redshift engineering’s advanced table design playbook: preamble, prerequisites, and prioritization」(Amazon Redshift エンジニアリングの高度なテーブル設計プレイブック: 前文、前提条件、および優先順位の設定) を参照してください。

次のクエリを実行し、分散キーの基数を確認します。

SELECT <distkey column>, COUNT(*) FROM <schema name>.<table with distribution skew> GROUP BY <distkey column> HAVING COUNT(*) > 1 ORDER BY 2 DESC;

注: ソート手順を回避するには、ORDER BY 句で SORT KEY 列を使用します。ソートステップでメモリが過剰に使用されると、ディスクスピルが発生することがあります。詳細については、「ソートキーの使用」を参照してください。

フィルタリングされた結果セットでカーディナリティの高い列を選択して、そのデータ分散を表示します。テーブルの分散スタイルの詳細については、「最適な分散スタイルを選択する」を参照してください。

分散キーのデータベースブロックがクラスターにマッピングされる方法を確認するには、Amazon Redshift table_inspector.sql ユーティリティを使用します。

クエリ処理

クエリに割り当てられているメモリを確認します。クエリの処理中に、クエリの中間結果が一時ブロックに保存される場合があります。十分な空きメモリがない場合、テーブルはディスクに書き込まれてディスクを圧迫します。中間的な結果セットは圧縮されないため、使用可能なディスク容量に影響します。詳細については、クエリに割り当てられてメモリが不十分、を参照してください。

Amazon Redshift のデフォルトは、均等な分散のテーブル構造であり、一時テーブル用に列エンコードは行いません。ただし、SELECT...INTO 構文を使用している場合は、CREATE ステートメントを使用します。詳細については、「Top 10 performance tuning techniques for Amazon Redshift」(Amazon Redshift のパフォーマンスチューニングテクニックのトップ 10) を参照してください。「ヒント #6: 一時テーブルの非効率的な使用に対処する」の指示に従ってください。

クエリに十分なメモリが割り当てられていないときは、SVL_QUERY_SUMMARY 内のステップを確認してみてください (is_diskbased が [true] である場合)。この問題を解決するには、クエリスロットの数を増やして、クエリにより多くのメモリを割り当てます。クエリのスロットを一時的に増やす方法の詳細については、wlm_query_slot_count を参照するか、WLM を調整して混合ワークロードを実行します。また、WLM クエリモニタリングルールを使用すると、入出力の多いクエリを識別しながら、大量の処理負荷に対処することもできます。

VARCHAR (MAX) 列を含むテーブル

VARCHAR または CHARACTER VARYING 列で、データをディスクに格納する際に省略できる空白が、末尾に付加されていないか確認します。末尾の空白は、クエリ処理中メモリ内の全長 (VARCHAR の最大値は 65535) を占める可能性があります。可能な限り最小の列サイズを使用することがベストプラクティスです。

最大列幅を持つテーブルのリストを生成するには、次のクエリを実行します。

SELECT database, schema || '.' || "table" AS "table", max_varchar FROM svv_table_info WHERE max_varchar > 150 ORDER BY 2;

幅広い VARCHAR テーブルの列の true の幅を識別して表示するには、次のクエリを実行します。

SELECT max(octet_length (rtrim(column_name))) FROM table_name;

このクエリの出力で、長さがユースケースに適合しているかどうかを検証します。列の長さが最大で必要を超えている場合は、必要な最小サイズに長さを調整します。

テーブル設計の詳細については、「Amazon Redshift テーブル設計のベストプラクティス」を参照してください。

列の高圧縮

[ANALYZE COMPRESSION] (圧縮分析) を使用するか、Amazon Redshift の自動テーブル最適化機能を使用して、すべての列 (ソートキーを除く) をエンコードします。Amazon Redshift は、列のエンコーディングを提供します。この機能を使用するのがベストプラクティスです。これは、読み取りパフォーマンスを向上させ、全体的なストレージ消費量を削減します。

メンテナンスオペレーション

Amazon Redshift データベースのデータベーステーブルが定期的に分析およびバキューム処理されていることを確認します。統計情報がないテーブルに対して実行されているクエリをすべて特定します。統計情報がないテーブルに対してクエリが実行されないようにすることで、Amazon Redshift は不要なテーブル行をスキャンせずに済みます。これは、クエリ処理の最適化にも役立ちます。

注: VACUUM や DEEP COPY などのメンテナンスオペレーションでは、ソートオペレーションにより一時ストレージ領域が使用されるため、ディスク使用量が一時的に急増することが予想されます。

たとえば、次のクエリは、Amazon Redshift の古くなった統計を特定するのに役立ちます。

SELECT * FROM svv_table_info WHERE stats_off > 10 ORDER BY size DESC;

また、ANALYZE コマンドを使用して、テーブル統計の表示および分析を行います。

メンテナンス操作の詳細については、「Amazon Redshift Analyze & Vacuum schema utility」を参照してください。

クロス結合を持つデカルト積

デカルト積を含むクエリを検索するには、クエリの EXPLAIN プランを使用します。デカルト積は、関係性のないクロス結合なので、ブロック数を増やす可能性があります。このクロス結合により、メモリ使用率が高くなり、ディスクに書き込まれるテーブルが増える可能性があります。クロス結合が JOIN 条件を共有していない場合、結合は 2 つのテーブルのデカルト積を生成します。この場合、1 つのテーブルのすべての行が、もう 1 つのテーブルのすべての行に結合されます。

クロス結合は、ネストされたループ結合として実行されることもあり、処理に最も時間がかかります。ネストされたループ結合により、全体的なディスク使用量が急増します。詳細については、ネステッドループにあるクエリの特定、を参照してください。

最小テーブルサイズ

同じテーブルでも、クラスターによってテーブルサイズが異なる場合があります。次に、最小テーブルサイズは、列の数と、テーブルに SORTKEY があるか、およびスライスの数が入力されているかどうかによって決まります。最近 Amazon Redshift クラスターのサイズを変更した場合、ディスクストレージ全体に変化が見られる可能性があります。これはスライス数が変化したことが原因です。Amazon Redshift は、各テーブルで使用されるテーブルセグメントもカウントします。詳細については、Amazon Redshift クラスターのテーブルが想定と異なるディスクストレージを消費していますが、なぜですか?、を参照してください。

廃棄ブロック

廃棄ブロックは、Amazon Redshift テーブルへの WRITE トランザクションが発生し、同時に読み取りも実行されている場合に生成されます。Amazon Redshift は、書き込みオペレーションの前にブロックを保持して、同時読み取りオペレーションの一貫性を保ちます。Amazon Redshift ブロックは変更できません。InsertUpdate、または Delete の各アクションは、新しいブロックのセットを作成し、古いブロックを廃棄済みとしてマークします。

テーブルのトランザクションが長時間実行されることが原因で、廃棄ブロックがコミット段階でクリアされないことがあります。廃棄ブロックは、同時に実行されている ETL ロードが多すぎる場合にもクリアに失敗することがあります。Amazon Redshift はトランザクションの開始時点からデータベースをモニタリングするため、データベースに書き込まれたテーブルにも廃棄ブロックが保持されます。長時間実行されるテーブルトランザクションが、定期的かつ複数のロードにわたって発生した場合、廃棄ブロックが蓄積されて、ディスクがいっぱいになるエラーが発生する可能性があります。

commit コマンドを実行して、Amazon Redshift に廃棄ブロックに関する分析を強制的に実行させることもできます。

アクティブな実行時間の長いクエリがある場合は、commit コマンドを使用して、クエリを終了 (および後続のすべてのブロックを解放) します。

begin;
create table a (id int);
insert into a values(1);
commit;
drop table a;

その後、廃棄ブロックを確認するには、次のクエリを実行します。

select trim(name) as tablename, count(case when tombstone > 0 then 1 else null end) as tombstones from svv_diskusage group by 1 having count(case when tombstone > 0 then 1 else null end) > 0 order by 2 desc;

大きなファイルのコピー

COPY オペレーション中に、十分なストレージが利用可能であっても、Disk Full (ディスクがいっぱいです) エラーが発生する可能性があります。このエラーは、ソートオペレーションがディスクにスピルされ、一時ブロックが作成される場合に発生します。

Disk Full エラーメッセージが表示された場合は、STL_DISK_FULL_DIAG テーブルを確認します。エラーの原因となったクエリ ID と作成された一時ブロックを確認してください。

select '2000-01-01'::timestamp + (currenttime/1000000.0)* interval '1 second' as currenttime,node_num,query_id,temp_blocks from pg_catalog.stl_disk_full_diag;

その他のベストプラクティスについては、「データをロードするための Amazon Redshift のベストプラクティス」を参照してください。

追加のトラブルシューティング

Amazon Redshift コンソール の [パフォーマンス] タブで、ディスクの使用率を確認します。各クラスターノードに対して、Amazon Redshift は追加のディスクスペースを提供します。これは、名目上のディスク容量よりも大きくなります。

使用率の急激なスパイクに気付いた場合は、STL_QUERY を使用して、実行中のアクティビティとジョブを特定します。ディスクが書き出されたときに実行中のクエリをメモします。

select * from stl_query where starttime between '2018-01-01 00:30:00' and '2018-01-01 00:40:00';

注: スパイクが発生した時刻で値を更新します。

上位 20 のディスク書き出しクエリを特定するには、次のクエリを実行します。

select A.userid, A.query, blocks_to_disk, trim(B.querytxt) text from stl_query_metrics A, stl_query B where A.query = B.query and segment=-1 and step = -1 and max_blocks_to_disk > 0 order by 3 desc limit 20;

blocks_to_disk 列の値を表示して、ディスクが書き出されていることを特定します。必要であれば、大量の書き出しが行われているクエリを終了します。次に、クエリを再実行する前に、クエリに追加のメモリを割り当てます。詳細については、「STL_QUERY_METRICS」を参照してください。

クエリがディスクに正しく書き込んでいるかどうかを確認するには、次のクエリを実行します。

SELECT q.query, trim(q.cat_text)
FROM (
SELECT query,
replace( listagg(text,' ') WITHIN GROUP (ORDER BY sequence), '\\n', ' ') AS cat_text
FROM stl_querytext
WHERE userid>1
GROUP BY query) q
JOIN (
SELECT distinct query
FROM svl_query_summary
WHERE is_diskbased='t' AND (LABEL ILIKE 'hash%' OR LABEL ILIKE 'sort%' OR LABEL ILIKE 'aggr%' OR LABEL ILIKE 'save%' OR LABEL ILIKE 'window%' OR LABEL ILIKE 'unique%')
AND userid > 1) qs
ON qs.query = q.query;

このコマンドは、ディスクにスピルしているクエリも識別します。


関連情報

パフォーマンス

Amazon Redshift システムの概要

AWS公式
AWS公式更新しました 1年前
コメントはありません

関連するコンテンツ