最近 SQL にはまっているので、ついでに Rails というか ActiveRecord で発行された SQL query をカウントする gem を書いた。
Installation
gem 'a_r_q_logger'
せつめい
ActiveRecord::Base
サブクラスのインスタンス生成をできるだけ抑えれば、それだけ処理時間が抑えられるのは自明とされています。
そこで、今は、できるだけ少ない queries に抑えることを目的として SQL の練習をしていますので、すぐわかるようにしました。
その練習を進めていく上で、その 1 query の処理時間が気になっており、SQL のみの処理時間もとれるようにしましたというか、出発点はこっちです。
pry(main)> ARQLogger.log { 3.times { TestModel.has_children(10).map(&:children_count) } } => #<struct ARQLogger::Result count=3, msec=1508.4>
from
句で前もって as
しておくのと、CASE
の WHEN
ごとに (複数の) 集約関数を書くのではどっちが速いのか気になって、こういうことをしていたのです。 (おそらくオプティマイザがいい感じにしてくれるおかげで、CASE
に同じ式を何回も書くほうが速かった)
テストでも使える
query を抑えようと書いたかっこいい生 SQLが、善意の第三者により書きかえられるということはありがちなことですが、amount of queries を抑えようと書いた生 SQL が、その善意により too many queries になっては目もあてられません。
query 発行量はコントロールできる要素ですから、これはテストで縛っておくことができます。
たとえば以下は N + 1 の解決法でよく出てくる includes
の付与テストです。
it do expect(ARQLogger.log { TestModel.includes(:test_child_models).all.each { |m| m.test_child_models.map(&:name) } }.count).to eq(2) end
it do expect(ARQLogger.log { TestModel.all.each { |m| m.test_child_models.map(&:name) } }.count).to eq(11) end
久しぶりに gem を書くのが目的だった
どこかにありそうだなと思って軽く調べて、そんな感じの gem もありましたが軽く無視って書きました。
たのしかたです。