ActiveRecordで直接アダプタから結果を受け取る

「実践Rails」を読んでいたらP178のあたりで「これはいい!!」と思う内容が、、、しかし試してみると一番目のカラムしかとれてないよ。。。。RailsAPIドキュメントを読んでみると

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#M001465

# File vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 26
26:       def select_values(sql, name = nil)
27:         result = select_rows(sql, name)
28:         result.map { |v| v[0] }
29:       end

わざわざ一番目の値のみ取得しています。どうしてこんなことをしているの?他所でつかってるんだろうかね?まぁ私の小さな頭ではわからんのでこいつは置いておいて、初っ端に感動したことを実現したければ「select_rows」を直接使えばいいのかなと思いちょいと書き書き

require 'rubygems'
require 'activerecord'
require 'pit'

config = Pit.get("mysql_test", :require => {
        "host" => "host in mysql_test",
        "username" => "your username in mysql_test",
        "password" => "your password in mysql_test",
        "database" => "database in mysql_test"
})

ActiveRecord::Base.establish_connection(
:adapter  => "mysql",
:host     => config['host'],
:username => config['username'],
:password => config['password'],
:database => config['database'],
:socket => "/var/lib/mysql/mysql.sock",
:encoding =>"utf8")

class << ActiveRecord::Base
  def select_rows(sql)
    connection.select_rows(sanitize_sql(sql))
  end
end

query = "select id,name from contents where id > ? limit 0,3"
p ActiveRecord::Base.select_rows([query,5])

#=>
[["6", "hoge"], ["7", "ugo"], ["8", "nana"]]

いいね。
ちょっとベンチでも計ってみるかとquery以下を書き換える

query = "select * from contents where id > ? limit 0,100000" # ここのlimitを書き換える

# warm-up
ActiveRecord::Base.select_rows([query,rand(100000)])

Benchmark.bm do |job|
  job.report {
    ActiveRecord::Base.select_rows([query,rand(100000)])
  }
  job.report {
    ActiveRecord::Base.find_by_sql([query,rand(100000)])
  }
end
ベンチ結果(三回実行)
100レコード
      user     system      total        real
  0.000000   0.000000   0.000000 (  0.004188)
  0.000000   0.000000   0.000000 (  0.007171)
      user     system      total        real
  0.000000   0.000000   0.000000 (  0.004254)
  0.010000   0.000000   0.010000 (  0.007426)
      user     system      total        real
  0.000000   0.000000   0.000000 (  0.004416)
  0.000000   0.000000   0.000000 (  0.006560)

10000レコード
      user     system      total        real
  0.070000   0.020000   0.090000 (  0.280001)
  0.310000   0.050000   0.360000 (  0.581231)
      user     system      total        real
  0.060000   0.020000   0.080000 (  0.313520)
  0.310000   0.050000   0.360000 (  0.556932)
      user     system      total        real
  0.060000   0.020000   0.080000 (  0.260485)
  0.300000   0.050000   0.350000 (  0.570325)

100000レコード
      user     system      total        real
  0.920000   0.330000   1.250000 (  2.955603)
  7.470000   0.510000   7.980000 (  9.847504)
      user     system      total        real
  0.900000   0.310000   1.210000 (  3.012176)
  7.490000   0.530000   8.020000 ( 10.106686)
      user     system      total        real
  0.920000   0.320000   1.240000 (  3.001611)
  7.500000   0.530000   8.030000 ( 10.156798)

結果

かりかりに動かなきゃいけないバッチだけど、直接アダプタをさわりたくはない!!何とかパフォーマンスを稼げんものかなぁぁって時の選択肢として頭の片隅に置いておいてもいいと思う。