デジちゃいむ を開発している WASD Inc. の shinnoki です。
デジちゃいむではエラーが発生した場合に Sentry, Datadog, AWS Chatbot などを使い社内の Slack に流しているのですが、最近そこにリクエストのタイムアウトと思われるエラーが見受けられるようになりました。 (呼び出しができなかったお客様、店舗様にはご不便をおかけいたしました。)
決まってピークタイムに発生するため、アクセス数やレコード数の増加に伴ってデータベースがボトルネックになっていることが疑われました。
デジちゃいむでは Amazon Aurora をメインのデータベースとして使っているのですが、今回の調査と改善に Performance Insights という機能を使ってみたところとても便利だったのでまとめました。
Performance Insights の有効化
AWS コンソール上でデータベースを作成した場合は Performance Insights がデフォルト設定で有効になっていますが、もし有効になっていなければまず Performance Insights の設定を変更する必要があります。
Performance Insights の有効化は無停止で即時反映させることができます。
今回は AWS CDK によって管理している Amazon Aurora インスタンスでしたが enablePerformanceInsights オプションはデフォルトで無効なため、これを有効にしてデプロイすることで即時反映されました。
Performance Insights の利用は無料で、デフォルト設定では 7 日間まで履歴をさかのぼることができますが、有料で設定を変更して 2 年間まで履歴を保持することもできます。
Performance Insights の表示
Performance Insights の画面を表示するには対象のデータベースの「現在のアクティビティ」をクリックするか、左側のメニューから「Performance Insights」をクリックした上でデータベースを選択します。
データベースのボトルネックを調査するには「データベース負荷」と「トップ SQL」というグラフを見ます。
Performance Insights を途中から有効化した場合、有効になった時点からのグラフが表示されます。
ここでは AAS という指標が使われています。
AAS というのは 「平均アクティブセッション」の略で、ある時点で見たときにのその SQL の結果待ちのセッション数を示しています。
AAS はレスポンス時間が長くなったりアクセス数が増えるほど大きくなるので、ざっくりとデータベースに対する負荷を示す値として使えます。
Performance Insights の紹介 にもこのように書いてあります。
利点
使いやすい
Performance Insights は IT ゼネラリストにもデータベースエキスパートにも向いています。手動で相関処理が必要な複数のグラフを表示する代わりに、すべてのコアパフォーマンスの情報を 1 つのチャートに集約するシンプルなインターフェイスを提供します。
負荷が高いときは、CPU 使用率の高さ、ロックの待機、I/O レイテンシーなどのボトルネックのタイプを簡単に識別し、ボトルネックとなっている SQL ステートメントを表示させることができます。
実際にやったこと
トップ SQL を見て、一番上位の SQL だけ水色の IPC:ExecuteGather
が目立つのでこの SQL の AAS を下げることを目標にしました。
SQL ステートメントは途中で省略されてしまいますが、だいたいあたりをつけることができるため、それをもとに調査を進めました。
デジちゃいむではデータベースから GraphQL API を生成してくれる Hasura をつかっているのですが、トップ SQL に関連するテーブルの設定を確認したところ、複雑なパーミッションを設定してしまっていたことによって負荷の高い SQL が高頻度で実行されていそうなことがわかりました。
またこちらは今回は大きな改善には繋がらなかったのですが、同時にインデックスも見直しました。 PostgreSQL の場合外部キーの設定とインデックスの作成が独立しているため、外部キーを設定していてもインデックスが作成されていないことによりパフォーマンスに支障がでることがよくあります。
設定変更前後での Performance Insights 上でのデータベース負荷のグラフが以下になります。
他の SQL もあるので負荷の総量については一概に言えないものの、明らかに負荷の性質が変わったことがビジュアル的に分かりました。
実際に、この修正を行ってから今までのようなエラーが飛んでくることはなくなっていますので、一定の効果はあったのかなと思います。
まとめ
データベースの負荷については、もちろん実装時に負荷まで考えることができるのが理想なのですが、データ数が増えて元々問題のなかったクエリの負荷が増大するということはよくありますので、今回のようにデータベースをブラックボックス的に調査することはどちらにしろ必要になってきます。
Performance Insights を使うことで詳しい調査に時間をかけなくてもとりあえず「トップ SQL」の上から解消していけばいずれはデータベースのパフォーマンス向上が見込めるというのはとてもわかりやすくて良いなと思いました。
機能が豊富なことよりも、シンプルに 1 つのメトリクスに集中できるというのはそれだけで価値がありますね。
稼働中のデータベースに対しても無停止で有効化できますので、データベースのパフォーマンスを見直したいけどどこから手をつけていいか分からないというときに強い味方かなと思います。