RDSのPerformance Insightsについて今更改めて
しかしAWSのドキュメントってフレンドリーさが何かないんだよなあ、、読むと丁寧なのは別るんだけど、、なんでやろデザイン?
使えるエンジンサイズ
Amazon RDS DB エンジンとインスタンスクラスでサポートされている Performance Insights
にあるように、まとめると、small
以下のインスタンスでは使えないということ。逆にmedium以上であれば使った方がよいという気がする。
料金
Performance Insights の料金とデータ保持によると
デフォルトでは、
Performance Insights
には、7 日間のパフォーマンスデータ履歴と 1 か月あたり 100 万件の API リクエストを含む無料利用枠が用意されています。
ということなんで小さなサービスであれば7日分のデーターがあればほとんど無料でいける。従ってmedium以上であれば使った方がよいと書いている。
では使ってみよう
有効化
こんな感じでonにする。
見てみる
まあこれはダミーデーターとおもってもらいたいんですけど、[+]のところで開閉できる。すると
このようなルーピーなクエリーを見る事ができる。これはまあN+1って奴すね。まあ、あとrowの数的にindex化されてないので二重苦みたいになってるんだろう。
ヘッダ行の解説(by ChatGPT)
- wait によるロード (AAS)
- SQL ステートメント
- Calls/sec
- Avg latency (ms)/call
- Rows examined/call
とこれ以外にもヘッダはあるんだけど、とりあえずこれだけ。
ChatGPTによる解説
wait によるロード (AAS)
AAS
(Average Active Sessions
)は、データベースにおける平均的なアクティブセッション数を示します。特に「wait によるロード」は、SQLクエリがCPU、I/O、ネットワーク、ロックなどでリソースを待機している状態の負荷を示します。
解釈:
- 値が高いほど、SQLクエリがリソース待ち状態である可能性が高くなり、パフォーマンスボトルネックを引き起こしている可能性があります。
- 各リソースの「待機イベント」ごとに分析することで、ボトルネックの原因を特定できます。
SQL ステートメント
実行されているSQLクエリの内容を示します。
解釈:
- この項目を見ることで、
どのクエリが問題を引き起こしているのか
特定できます。 - クエリ内容を確認し、インデックスの不足、冗長な条件、結合処理の非効率さなどを特定します。
Calls/sec
単位時間(1秒あたり)におけるSQLステートメントの呼び出し頻度(実行回数)を示します。
解釈:
- 値が高いSQLは、頻繁に実行されているためシステムへの負荷が大きい可能性があります。
- 頻繁に実行されるクエリは、特に効率化の対象になります(例: キャッシュの利用、インデックス追加など)。
Avg latency (ms)/call
SQLクエリ1回の実行にかかる平均時間をミリ秒単位で示します(平均レイテンシ)。
解釈:
- レイテンシが長いほど、ユーザーやシステムに影響を与える可能性が高いです。
- 平均実行時間が長いクエリは、クエリの再構築や最適化が必要な場合があります。
- 長いレイテンシの原因には、以下が考えられます:
- 非効率なクエリ設計(例: フルテーブルスキャン)
- 適切なインデックスがない
- 大量データの処理
Rows examined/call
SQLクエリ1回の実行で検査(読み取り)された行数を示します。
解釈:
- 値が高いほど、データベースが無駄な行を読み取っている可能性があります(効率の低いクエリ)。
- 行数が多い場合は、以下の原因をチェックします:
- 適切なインデックスがない。
- 条件が曖昧で、過剰な行を検索している。
- テーブル結合が非効率である。
例えば
このようなQueryはExplainしてみたところノーインデックスで15000行が返却されていたんだけど、これに適切にインデックスを与えて効率化して様子を見る。このように割と少ない行数でここに出てるのは何となく N+1 っぽくなってるのが多そうだ。スローログで検知が難しいからなあ...
EXPLAIN SELECT COUNT(*) AS `cnt` FROM `course_user` `CU` WHERE `CU`.`course_id` = 123 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: CU
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 24634
filtered: 10.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
こんなんとかも
ALTER TABLE `course_user` ADD INDEX idx_course_id (`course_id`);
なんかして
EXPLAIN SELECT COUNT(*) AS `cnt` FROM `course_user` `CU` WHERE `CU`.`course_id` = 123 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: CU
partitions: NULL
type: ref
possible_keys: idx_course_id
key: idx_course_id
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
とかいう形でどんどん改善していく
良い所
スロークエリーログでは掴み辛いN+1が比較的検知しやすいように思う。まあ最終的にはこれはインデックスというよりはPGの方も何とかしないといけないんだろうとは思いますけどね。
Discussion