Кто дергал этот запрос и послал его?

October 20, 2016

Один из важных моментов оптимизации рейлс-приложения, на котором кстати часто вся оптимизация и заканчивается, это уменьшение количество запросов в базу.

Самый простой способ понять что нужно оптимизировать, пожалуй - посмотреть в ньюрелике под вашим штатным трафиком, какой экшен занимает больше всего времени. После этого запустить приложение локально и начать изучать какие строчки кода тревожат базу. Многие проблемы легко понять просто по логам. Убрав тяжелые N+1, а также большинство запросов CACHE, вы сильно поможете приложению.

Note: Все СACHE очень рекомендую убирать (один из вариантов - смотрим и ностальгируем Caching with Instance Variables), так как несмотря на то что запрос в базу не посылается, ActiveRecord кэширует запрос на уровне SQL, все AR-объекты пересоздаются с нуля, что жгет CPU и негативно влияет на произодительность.

Также есть два удобных инструмента, которые помогут справится с задачей. Старый, добрый rails-footnotes на страницах рисует полную информацию о всех запросах.

Так как футнотес наверняка будет рвать верстку, то я его обычно подключаю с помощью такой конструкции:

defined?(Footnotes) && Footnotes.setup do |f|
  f.enabled = -> { File.exists?(Rails.root.join("FOOTNOTES")) }
end

Теперь, чтобы включить футноты достаточно создать в корне файл touch FOOTNOTES. Если его удалить, то футноты отключатся без перезагрузки сервера. Естественно на продакшене футноты не надо включать никогда :smile:.

Однако футноты не помогут, если таинственный запрос к базе в AJAX'е, а по коду сходу не понятно в каком колбеке или библиотеке он вызывается. Решение тоже есть - это ActiveSupport::Notifications. В инициалайзере подписываемся на SQL-запросы и находим негодяя:

ActiveSupport::Notifications.subscribe "sql.active_record" do |*args|
  puts caller if args[4][:name] == "User Load"
end

Берегите свою базу смолоду и она вам верно прослужит многие годы :smile:.

comments powered by Disqus