低速クエリのログでの記録は、Railsアプリケーションのパフォーマンスチューニングにおいて非常に重要な要素です。Railsには、 Active Support::Notificationsと呼ばれる、時間のかかっているクエリをログに記録するメカニズムが用意されています。

この記事では、Active Support::Notificationを使ってRailsアプリケーションの遅いクエリをログに記録する方法をご紹介します。また、遅いクエリのログを分析してパフォーマンスの問題を特定し、調整するヒントにも触れたいと思います。

クエリの遅延とは

そもそも時間のかかっているクエリとは、実行に一定のしきい値以上の時間がかかるクエリのことです。クエリの「遅延」を規定する絶対的な基準値はありません。アプリケーションとそのパフォーマンス要件によって異なります。しかし、目安としては、100ミリ秒以上かかるクエリはすべて低速のクエリであると考えるのがよいでしょう。

なぜ遅いクエリのログを取ることが重要なのか

遅延の見られるクエリをログに記録することが重要です。これにはいくつもの理由があります。

まず、遅いクエリはアプリケーションの根本的なパフォーマンス面での問題の兆候となる可能性があります。クエリの遅延状況をログに記録することで、そのような問題を早い段階で特定し、調整のための手段を講じることができます。予防は治療に勝ります。

第二に、遅いクエリは、アプリケーションの潜在的なセキュリティ面での脆弱性を特定するのに有効です。例えば、SQLインジェクション攻撃を原因とする低速クエリは、脆弱性を特定し、それを軽減する策を講じるきっかけになります。

第三に、時間のかかっているクエリに狙いを定めることで、アプリケーションのパフォーマンスを改善することができます。

遅いクエリのログを分析することで、パフォーマンスの問題を最も引き起こしているクエリを特定し、そのクエリを最適化することが可能です。具体的には、Active Support::Notificationsを使用して、アプリケーションの低速クエリイベントを記録することができます。

Active Support::Notificationsとは

Active Support::Notificationsは、アプリケーションのパフォーマンスや動作について深い洞察を必要とするRails開発者に欠かせない機能です。コード内で発生した特定のイベントを追跡し、その実行に関するデータを収集することができます。

その機能を理解し、効果的に活用することで、Railsアプリのパフォーマンス、保守性、全体的な健全性を大幅に引き上げることが可能です。

以下、Active Support::Notificationsの概要と主な利点を説明します。

機能

  • インストルメンテーション:ActiveSupport::Notifications.instrumentメソッドを使用すると、Railsアプリケーションの特定のイベントを追跡、監視できます。このメソッドは名前、ペイロード(任意のデータ)、実行するコードブロックを受け取ります。
  • ペイロード:ペイロードには、インストルメンテーション対象のイベントに関連する追加データを渡すことができます。これには、タイムスタンプ、ユーザーID、データベースクエリの詳細などが含まれます。
  • サブスクライバー:ブロックが実行された後、Active Supportは登録されたサブスクライバーに名前とペイロードを含む通知を送信します。このサブスクライバーが、情報を処理し、イベントに基づいて特定のアクションを実行できます。

メリット

  • パフォーマンスのモニタリング:主要なイベントを追跡することで、その実行時間を把握し、アプリケーション内のパフォーマンスのボトルネックを特定できます。これにより、コードを最適化してRailsアプリ全体のパフォーマンスを改善可能です。
  • デバッグ:通知からは、アプリケーションのフローに関する貴重な洞察が得られ、これを使って問題を診断することができます。ペイロードのデータから、実行時の予期せぬ動作やエラーが明らかになります。
  • カスタムインストルメンテーション:カスタムインストルメンテーションとサブスクライバーを作成することで、Active Support::Notificationsの機能を拡張できます。これにより、アプリケーション固有のニーズに関連する特定のイベントを追跡可能です。
  • 他のライブラリとの統合:Action CableやActiveJobのような数多くのRailsライブラリから、Active Support::Notificationsを活用したパフォーマンスデータとイベントトラッキングの機能が提供されています。

Active Support::Notificationsで遅いクエリを記録する方法

Active Support::Notificationsは、アプリケーションで発生したイベントを記録するためのRailsの組み込みメカニズムです。Active Support::Notificationsを使用して遅いクエリをログに記録するには、以下のコード例をイニシャライザ(config/initializers/error_notifications.rbなど)に記述して、アプリケーションの起動時に実行されるようにします。または、このコードを特定のコントローラやモデルに追加して、 対象とするロギングを行うこともできます。

config.active_support.Notifications.subscribe('sql.active_record') do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)
  if event.duration > 100
    Rails.logger.info "Slow query: #{event.payload[:sql]}"
  end
end

このコードは、実行に100ミリ秒以上かかるすべてのSQLクエリをログに記録します。

ログには、SQL文、クエリの実行時間、クエリが実行されたファイル名、行番号などが記載されます。

遅いクエリのログを分析する方法

低速クエリのログを記録し始めたら、ログを解析してパフォーマンス上の問題を引き起こしているクエリを特定する作業に移行しましょう。ログを分析し、時間のかかっているクエリを特定する方法はいくつかあります。

1つは、Rails Performance Dashboardのようなツールを使う方法です。Rails Performance Dashboardでは、グラフィカルインターフェースを通じてクエリログを表示し、時間のかかっているものを分析することができます。

ログから遅いクエリを分析するもう1つの方法として、テキストエディタやスプレッドシートのプログラムを使用することもできます。テキストエディタやスプレッドシートを使用して、低速クエリのログを期間、SQLステートメント、ファイル名で並べ替えたりフィルタリングしたりできます。

これにより、パフォーマンスの問題を最も引き起こしているクエリを簡単に発見できます。

遅いクエリを解決する方法

パフォーマンス面での問題を最も引き起こしているクエリを特定したら、そのクエリに対処するステップへと進みましょう。遅いクエリの解決方法は複数あります。

まずはSQL文を最適化する方法です。SQL文を最適化するには、インデックスを使用したり、制約を追加したり、より効率的なクエリメソッドを使用したりできます。

低速クエリを解決するもうひとつの方法は、クエリの結果をキャッシュすることです。クエリの結果をキャッシュするには、RailsキャッシュストアデータベースキャッシュRedis、Memcachedなど)を使うことができます。

ページ分割を実装してデータ量の大きなものを小さなページに分割することで、パフォーマンスが向上し、メモリ使用量を減らすことが可能です。

また、バックグラウンドジョブを実行し、長時間実行するクエリをバックグラウンドジョブにオフロードして(SidekiqやResqueの使用など)、ウェブリクエストがブロックされるのを防ぐのも一つの手です。

まとめ

Active Support::Notificationsは、低速クエリを記録するのに効果を発揮するRails組み込みのメカニズムです。遅いクエリのログでの記録は、Railsアプリケーションのパフォーマンスチューニングに欠かせないステップです。クエリをログに記録することで、パフォーマンスの問題を早い段階で特定し、改善のための策を講じることができます。

Active Support::Notificationsを使用して時間のかかっているクエリをログに記録し、その内容を分析すれば、パフォーマンス面での問題を引き起こしている厄介なクエリを特定することができます。パフォーマンス低下の原因を突き止めたら、その解決へと進みましょう。

プロジェクトの構造を整えた上で、このような施策を用意し、チームに追加のリソース(若手開発者など)を確保しタスクを一任することで、作業最適化が捗るはずです。また、モニタリングチームやシニアレベルの開発者を巻き込むことで、より優れたパフォーマンスを目指すこともできるでしょう。遅延クエリの改善からは大きなリターンが見込めます。

問題が発生するのを待っているのでは「時既に遅し」です。特定のクエリが全体の生産性を落としてしまう前に、積極的に予防策を講じましょう。

Lee Sheppard

Lee is an Agile certified full stack Ruby on Rails developer. With over six years in the tech industry he enjoys teaching, coaching Agile, and mentoring others. Lee also speaks at tech related events and has a background in design and illustration.