😊

Datadogを活用したRailsアプリケーションのクエリ最適化の取り組み

に公開

この記事は、ポート株式会社 サービス開発部 Advent Calendar 2025 13日目の記事です。

はじめに

ポート株式会社で就活会議のバックエンドエンジニアをしているkawashimaです。

この記事では私たちのチームで実施しているパフォーマンス改善の取り組み、特にDatadogを活用したSQLクエリ最適化の取り組みについて紹介します。

取り組みの全体像

バックエンドチームでは定期的にアプリケーションのパフォーマンスを確認する時間を設けています。
Datadogでレイテンシの大きいページを確認するだけでも効果はありますが、具体的なパフォーマンスの悪化するケースに特化して効率の悪いクエリを検出し、改善を行っています。

主に以下の3種類の観点で定期的に監視・改善を行っています。

  1. スロークエリの検出
  2. N+1クエリの検出
  3. ActiveRecordの大量インスタンス化の検出

スロークエリの検出

Datadog APM のトレースクエリを使用し、リクエスト中に発生するスロークエリを検出しています。

以下はクエリの例です。 Traces matchingフィールドで ->トレースクエリ演算子 を使うことでrails サービスから呼び出される mysql サービスのSpanを検索しています。また、Resource ごとにグルーピングを行うことで、クエリの種類ごとに実行時間や件数を表示することができます。

N+1クエリの検出

スロークエリと同じく Datadog APM のトレースクエリを使用し、リクエスト中に発生するN+1クエリを検出しています。
先ほどと異なるのはwhere部分の絞り込みで、 span_count(b):>=N という絞り込みによって1リクエストにN件以上のSQLが発行されているTraceを検索することができます。

以下は発見したN+1クエリの例です。黄色のSpanがSQL発行に該当しており、大量にクエリが発行されていることがわかります。

開発時に bullet を使用したN+1の検出も行っていますが、本番環境との挙動が異なる場合や、コードレビューで見逃される場合もあるため、Datadogでの定期的な確認が効果的です。

ActiveRecordの大量インスタンス化の検出

Railsアプリケーションにおいて、ActiveRecordのインスタンス化は、実は無視できないコストがかかります。
大量のレコードを一度にロードするとメモリを圧迫するだけでなく、オブジェクト生成処理がCPUバウンドであるためRubyのGVL(Global VM Lock)によって他のスレッドの処理をブロックしてしまう可能性があります。

参考: RubyのGVLについて

DatadogのRubyトレーサーには active_record.instantiation.record_count という属性があり、これを利用することで「大量のActiveRecordオブジェクトを生成しているリクエスト」を特定できます。

これを利用して以下のようなクエリを作成できます。 @active_record.instantiation.record_count:>=N という絞り込みによってN件以上のレコードをインスタンス化している箇所を検出できます。

改善策としては以下のようなアプローチを取っています。

  • SQLを工夫し表示に不要なレコードの読み込みを避ける(limit や適切な絞り込み)
  • pluck を使用して、ActiveRecordオブジェクトではなく必要なカラムの値だけを取得する

まとめ

Datadogを活用することで、具体的なパフォーマンスの悪化するケースに特化してクエリを分析することができます。

  • トレースクエリによるスロークエリ・N+1クエリの検出
  • ActiveRecordインスタンス化数の監視によるCPU効率の改善

Datadog は非常に便利なサービスであり、他にも色々な活用方法があります。私もまだまだ知らない機能も多いので是非使いこなしてアプリケーションの改善に役立てていきましょう!

ポート株式会社 エンジニアブログ

Discussion