RailsでSlow Queryを自動検出する方法
開発が落ち着いてくると新規開発みたいな慌ただしさが減り、使い勝手を向上させるため、SQLのチューニングをする必要が発生します。
いわゆる保守フェーズになります。
その際に、sloq queryを自動的に検出できたら、より効率的になるのですがRailsだとかなり簡単だったのでご紹介します。
SQLの改善はやり方によって、1000倍ぐらいパフォーマンスが変わり、SEOの改善が起きたりとても良いのでぜひいろんなサービスに入れて良いサービスなると良いですね。
設定方法
簡単です。initializerでActiveSupport::Notificationsを使ってsql.active_recordをsubscribeするだけでした。
# config/initializers/slow_query_logger.rb
class SlowQueryLogger
def self.initialize!
ActiveSupport::Notifications.subscribe('sql.active_record') do |_name, start, finish, id, payload|
duration = finish.to_f - start.to_f
Rails.logger.debug("slow query detected: #{payload[:sql]}, duration: #{duration}")
end
end
end
SlowQueryLogger.initialize!
initializerにコードを書き、railsを再度起動してみると development.logには slow query detected とでるようになります。
slow query detected: SELECT `messages`.* FROM `messages` WHERE `messages`.`user_id` = 5 AND `messages`.`id` = 13 ORDER BY FIELD(messages.id, 13), duration: 0.004096031188964844
試しに表示しただけなので、実際に使えるコードはこんな感じになります。 3秒以上のqueryを検出してくれます。簡単ですね。
# config/initializers/slow_query_logger.rb
class SlowQueryLogger
MAX_DURATION = 3.0
def self.initialize!
ActiveSupport::Notifications.subscribe('sql.active_record') do |_name, start, finish, id, payload|
duration = finish.to_f - start.to_f
if duration >= MAX_DURATION
Rails.logger.debug("slow query detected: #{payload[:sql]}, duration: #{duration}")
end
end
end
end
SlowQueryLogger.initialize!
他にもrender時間の計測や特定のメール送信をフックしてslackに通知させたりできます。