Amazon Redshift DB開発者ガイド – クエリパフォーマンスチューニング(4).その他Tips

2013.09.03

クエリパフォーマンスチューニング第4弾はこれまでの3回分で紹介しきれなかったその他のドキュメントに関する部分です。

 

ディスクスペースの監視

ディスク容量に関する情報を取得する為に、STV_PARTITIONS,STV_TBL_PERM,STV_BLOCKLISTシステムテーブルを照会する事が出来ます。

注意:
これらのシステムテーブルにアクセスするには、スーパーユーザーとしてログインする必要があります。

STV_PARTITIONテーブルを使用して、ディスク領域を監視する事が出来ます。

次のクエリは1MBのディスクブロックで、表示上のディスク使用容量とキャパシティを返します。表示上のディスクスペースにはAmazon Redshiftが内部で使うために予約しているスペースが含まれているので、ユーザーが利用出来るディスクスペースの公称のディスク容量よりも大きいです。

Amazon Redshift管理コンソールの[パフォーマンス]タブで表示されているディスク領域の割合は、クラスタで使用されている名目上のディスク容量の割合をレポートしています。クラスタの名目上のディスク容量内で使用状況を維持する為に、統計で使用されるディスク領域の割合を監視する事をお勧めします。

重要:
クラスタの公称ディスク容量を超えないようにする事を、我々は強くお勧めします。
特定状況下で容量を超過する事は技術的に可能かも知れませんが、
公称ディスク容量を超過した場合、クラスタのフォールトトレランス(耐障害性)が減少し、データ損失のリスクが増大してしまいます。

select owner as node, diskno, used, capacity 
from stv_partitions 
order by 1, 2, 3, 4;

このクエリは、単一ノード上では以下の様な結果を返します。

node  | diskno | used | capacity
-------+--------+------+----------
     0 |      0 |  245 |   1906185
     0 |      1 |  200 |   1906185
     0 |      2 |  200 |   1906185
(3 rows)

詳細については、STV_PARTITIONSを参照してください。ディスク容量が不足した状態で起動する場合、計算ノードの数を増やしたり、より大容量のノードに変更する事が出来ます。Modifying a clusterをご参照ください。

あなたは、データベーステーブルに割り当てられたストレージの量を決定するためにSTV_BLOCKLISTSTV_TBL_PERMを使用する事が出来ます。

STV_BLOCKLISTシステムテーブルには、データウェアハウスクラスタ内の各テーブルに割り当てられたブロックの数に関する情報が含まれており、STV_TBL_PERMテーブルには、データベース内の全ての恒久的なテーブルのテーブルIDが含まれています。

SALESテーブルに割り当てられているブロック数を調べる為には、以下の問い合わせを実行します。

select tbl, count(*)
from stv_blocklist
where tbl in (
select id
from stv_tbl_perm
where name='sales')
group by tbl;

このクエリは以下の結果を返します。

tbl   | count
--------+-------
 100597 |   100
(1 row)

各データ・ブロックは1MBを専有しているので、100ブロック=ストレージの100MBとなります。詳細については、STV_BLOCKLISTSTV_TBL_PERMをご参照ください。

 

コンパイルされたコードのベンチマーク

Amazon Redshiftは、それぞれの実行計画のためのコードを生成するためのコードをコンパイルした後、計算ノードにコンパイルされたコード・セグメントを送信します。インタプリタを使用するオーバーヘッドが無くなる為、コンパイルされたコードは遥かに高速に実行されますが、最初に一番チープなクエリプランの為に幾つかのコードが生成、コンパイルされる時間のオーバーヘッドコストが常に掛かります。その結果、あなたがそのクエリを初めて実行した時のパフォーマンスは誤解を招く結果になる可能性があります。性能を評価する為には、常にそのクエリの2回目の実行時間を見る必要があります。

アドホッククエリ(特定の目的のために使用するクエリ)を実行する時のオーバーヘッドコストが特に顕著になるかもしれません。コンパイルされたコードはキャッシュされ、クラスタ内のセッションで共有されるので、同じクエリを後続で実行する際はたとえ、異なるクエリパラメータ、異なるセッションだったとしても、初期の生成とコンパイルのステップをスキップする事が出来、より早く実行する事が出来ます。

クエリの実行時間を比較する際は、1回目の結果を使用しないでください。その代わりに、2回目の実行時間を比較に使います。同様に、異なるクライアントから送られてきた同じクエリの性能を比較する際は注意してください。実行エンジンは、JDBC接続プロトコル及びODBCとpsql(libsql)接続プロトコル毎に異なるコードを生成します。2クライアントが異なるプロトコルを使用する場合、各クライアントは同じクエリに対して、コンパイルされたコードを生成するためにコンパイルされたコードを生成する為に初回のコストが掛かります。例えば、SQLWorkbenchはJDBC接続プロトコルを使用しますが、PostgreSQLの問い合わせユーティリティであるpsqlはlibpqと呼ばれるライブラリ関数のセットを用いて接続します。その為、実行エンジンは2つの異なるコンパイルされたバージョンのコードを生成します。しかし、同じプロトコルを使用する他のクライアントは、キャッシュされたコードを共有する事の恩恵を受ける事が出来ます。ODBCとlibpqでPsqlを実行するクライアントは、同じコンパイルされたコードを共有する事が出来ます。

 

JDBCフェッチサイズパラメータの設定

注意:
フェッチサイズはODBCではサポートされていません。

デフォルトでは、JDBCドライバは一度のクエリで全ての結果を収集します。結果として、JDBC接続を介して大量の結果を取得しようとすると、メモリ不足のエラーがクライアント側から発生する場合があります。あなたのクライアントが1回の(全件or0件の)フェッチ処理で結果セットを取得出来るようにするために、クライアントアプリケーションのJDBCフェッチサイズパラメータを設定します。

注意:
大規模なデータセットを抽出する必要が有る場合、Amazon S3にデータを移行する為に
UNLOAD文をを使用する事をお勧めします。
UNLOADを使用すると、計算ノードは直接データを転送する為に並行して作業を行います。
JDBCを使用してデータを取得すると、データはリーダーノードを介してクライアントに注ぎ込まれます。

最高のパフォーマンスを得るには、OutOfMemoryエラーとならない数値の最高値をフェッチサイズに設定します。より低いフェッチサイズの値は結果としてサーバを移動する時間が増え、結果実行時間が伸びてしまいます。サーバは、クライアントが結果セット全体を取得するまで、またはクエリがキャンセルされるまで、WLMクエリスロットと関連付けられたメモリを含むリソースを確保します。適切にフェッチサイズを調整すると、これらのリソースを他のクエリが利用出来るように、より迅速に解放する事が出来ます。JDBCフェッチサイズパラメータの設定詳細については、PostgreSQLドキュメントのGetting results based on a cursorをご参照ください。