皆さんこんにちは、AI SaaS事業本部 Digital Billder事業部 Devグループの御厨です!
私たちが開発・提供している Digital Billder は、建設業界における「見積・発注・請求」といった一連の業務をクラウドで一元管理できる Web アプリケーションです。
日々の業務の中で扱うデータ量も多く、請求書の検索体験を向上させることは、プロダクトの使いやすさに直結します。
今回は、その検索体験を改善するために、検索画面のパフォーマンス改善を担当しました。
当初は、
- SQLが重いのでは?
- インデックスが足りないのでは?
といった、よくある仮説から調査を始めました。
しかし実際に改善を進める中で、一番効いたのは別のポイントでした。
それは、
クエリを軽くする前に 「そもそも発行しすぎていないか」を疑うこと
本記事では、改善率(%) と Aurora Performance Insights の変化 を交えながら、検索画面パフォーマンス改善で得られた実務的な学びをまとめます。
- 改善の背景
- 今回やったこと
- 改善結果(改善率)
- Performance Insights から見た改善効果
- 今回一番効いた改善ポイント
- ここからは今回の改善を通して得た教訓です
- まとめ
- 今後の改善予定
- We’re Hiring!
改善の背景
対象となった検索画面では、以下の課題がありました。
- 初回表示・検索実行時に明確な待ちが発生する
- 条件を変更するたびに体感で遅さを感じる
- データ量増加に伴い、今後さらに悪化する懸念があった
実際にお客さんからも「検索が遅い」という指摘があり、UX的にも無視できない状態でした。
そのため、場当たり的な対処ではなく、計測を前提にしたパフォーマンス改善に取り組むことになりました。
今回やったこと
まず最初に SQL やインデックスを疑って Performance Insights とアプリのログを追いました。
その結果、ボトルネックは「クエリの発行回数が多い」ことに加えて、発行されているクエリ自体も重いことだと分かりました。
具体的には、一覧画面の検索で本来必要な情報以上に、一括操作で必要になる詳細情報まで同時に取得しており、結果として「重いクエリが短時間に何度も走る」状態になっていました。
そこで改善として、取得するデータを用途で分離しました。
- 検索(一覧表示)では、表示に必要な最低限の情報だけ取得する
- 一括操作を実行したタイミングでのみ、必要な詳細情報を追加で取得する
まずは改善結果からお伝えします。
改善結果(改善率)
計測条件
- 対象:請求書一覧の検索API(検索画面の「一覧取得」処理)
- 件数:100〜200件程度(企業・条件により前後)
- 計測環境:本番相当
- 指標:表示完了まで(ユーザー体感に近い指標)
一覧画面表示(担当請求書)
| 企業 | 改善率 |
|---|---|
| 企業A | 約74%改善 |
| 企業B | 横ばい(条件によりブレ) |
| 企業C | 約42%改善 |
| 企業D | 約38%改善 |
- 4社中3社で明確に改善
一覧画面表示(全社請求書)
| 企業 | 改善率 |
|---|---|
| 企業A | 約66%改善 |
| 企業B | 約41%改善 |
| 企業C | 約84%改善 |
| 企業D | 約58%改善 |
- 最大で80%超の改善が確認できました
一括操作(モーダル表示まで)
| 企業 | 担当請求書(改善率) | 全社請求書(改善率) |
|---|---|---|
| 企業A | 約31%改善 | 約38%改善 |
| 企業B | 横ばい | 約11%改善 |
| 企業C | 約31%改善 | 約39%改善 |
| 企業D | 約23%改善 | 約36%改善 |
体感としても「待たされる感覚がほぼなくなった」状態になりました。
Performance Insights から見た改善効果
検索画面改善を含むリリースを 12月5日 に実施しました。
Aurora Performance Insights を見ると、リリース前後で以下の変化が確認できます。

改善前(〜12/4)
- 平均アクティブセッション(AAS)が高止まり
- 負荷の大半を CPU が占有
- 検索操作が集中する時間帯でスパイクが頻発
改善後(12/5 以降)
- AAS が明確に低下
- CPU 由来の負荷が大きく減少
- 負荷スパイクの頻度・高さともに改善
DB のスケール(vCPU)を上げていないにも関わらず負荷が下がっている点からも、クエリの発行数そのものが減った効果が確認できました。
今回一番効いた改善ポイント
クエリを軽くする前に「発行しすぎていないか」を疑う
今回の改善で最も効果が大きかったのは、SQLそのものの最適化ではありません。
実際に起きていたのは、以下のような状態でした。
- 同一条件の検索が短時間に何度も発行されている
- 一覧取得・件数取得・補助データ取得で似たような重いクエリが複数回実行されている
- GraphQL resolver 経由で画面構造に引きずられたDBアクセスが発生している
これらを整理し、
- 不要な再検索の抑制
- 同一条件の検索結果の使い回し
- 一覧画面で本当に必要な項目だけを取得
といった対応を行いました。
結果として、SQL自体をほとんど変えずに大幅な改善が得られました。
ここからは今回の改善を通して得た教訓です
以降は、今回の改善を通して「今後も意識したい」と感じたポイントをまとめます。
ヤマ勘で改善しない。まずは計測する
パフォーマンス改善で一番避けるべきなのは、
「たぶんここが重い」
という推測だけで手を入れることです。
今回、必ず確認していたのは以下です。
EXPLAIN / EXPLAIN ANALYZE- Seq Scan / Index Scan
- JOIN 方法(Nested Loop / Hash Join など)
体感ではなく、実行計画と数値で判断する これを徹底しました。
GraphQL の resolver は特に注意が必要
GraphQL は便利な反面、裏で発行される SQL を意識しづらい仕組みです。
- フィールド追加がSQL増加につながる
- 素直に書くと N+1 が発生しやすい
実務では、
「この1リクエストで、何本SQLが出ているか」
を常に意識するようになりました。
実行計画は「環境ごとに別物」だと腹落ちした
今回の改善で改めて痛感したのは、実行計画は環境ごとに平気で変わるということです。
開発 / 検証 / 本番では、データ量・データの偏りが異なります。
その結果、同じSQLでも
- Index Scan が効く / 効かずに Seq Scan になる
- Nested Loop / Hash Join など JOIN 戦略が変わる
- Sort が発生して一気にコストが跳ねる
といった形で、ボトルネックが入れ替わります。
だからこそ、改善は「ローカルで速くなった」で満足せず、
本番相当のデータ量で成立するかを前提に評価するのが重要です。
可能であれば、本番相当環境で EXPLAIN (ANALYZE, BUFFERS) を確認しながら、
“本番のクエリ” を改善する意識を持つようになりました。
まとめ
検索画面のパフォーマンス改善は、
- SQLチューニング
- インデックス追加
- N+1 解消
といった定番施策も重要ですが、今回 一番効いたのは「無駄なDBアクセスを減らすこと」でした。
今後の改善予定
一定の改善はできたものの、企業・条件によってはまだ改善余地があります。今後は以下の改善を検討しています。
We’re Hiring!
燈では、プロダクトの新機能開発はもちろん、SaaSとしての基盤を活かした UX改善・パフォーマンス改善・運用コスト削減 など、“プロダクトを良くし続ける” 取り組みに興味があるエンジニアを募集しています。
興味がある方は、ぜひカジュアル面談でお話しましょう!