find方法の違いによるパフォーマンス(処理速度)テスト

環境

前回のフィルタテストと同じですが、

  • App Server
    • Amazon EC2: Large Instance
    • Apache: デフォルト設定
    • Ruby: 1.8.7
    • Passenger
      • RailsEnv: production
      • RailsMaxPoolSize: 30
      • RailsPoolIdleTime: 1200
    • Rails: 2.3.8
  • Request 兼 DB Server
    • Amazon EC2: Large Instance
    • DB: MySQL
      • my-innodb-heavy-4G.cnf を元にmax_connectionsなど4,5つ値を調整した設定を使用
    • ab (Apache Bench) でApp Serverに対してリクエス
      • 100件同時接続を5秒間続けて、どれくらいリクエストを処理できたかを見る
$ ab -c 100 -t 5 http://ec2-***.amazonaws.com/find_check

「select *」 VS 「select id」

全カラムを取得するのと、対象カラムをidだけに絞って取得する場合の比較

カラム数13のモデルの場合

13カラムの内訳: id, stringカラム1-5, integerカラム1-5, created_at, updated_at

下記結果の表の項目定義

  • all: Model.all
    • 全カラム取得(select *)
  • slct: Model.find(:all, :select => "id")
    • idのみ取得(select id)
  • all, slct の後の数字(1, 10, 100): 取得されるレコード数

 all 1slct 1all 10slct 10all 100slct 100
Complete requests 1877.1 1922.8 1776.5 1891.5 1219.8 1482.2
Requests per second 375.029 384.227 354.799 377.934 243.623 296.103

カラム数103のモデルの場合

103カラムの内訳: id, stringカラム1-50, integerカラム1-50, created_at, updated_at

 all 1slct 1all 10slct 10all 100slct 100
Complete requests 1801.6 1877 1509.7 1878.3 511.8 1529.2
Requests per second 359.862 374.8 301.463 375.075 102.025 305.372


予想通りだけど、取得対象を絞った方が速い。

「find_all_by」 VS 「conditions」

条件が1つの場合
  • 13カラムのモデルを使用(id, str1-5, int1-5, created_at, updated_at)
  • data
    • 計100レコード
      • id=1-50 のレコードには、str1='hoge', int2=1, str3='foo' が入っている (他はNULL)
      • str1, int2, str3 のマルチカラムインデックス

下記表の項目定義

  find_by cond placeholder cond
Complete requests 1422.4 1476.3 1457.2
Requests per second 284.058 294.529 290.91

条件が3つ
  • find_by: find_all_by_str1_and_int2_and_str3('hoge', 1, 'foo')
  • cond placeholder: find(:all, :conditions => ["str1 = ? AND int2 = ? AND str3 = ?", "hoge", 1, "foo"])
  • cond: find(:all, :conditions => "str1 = 'hoge' AND int2 = 1 AND str3 = 'foo'")

  find_by cond placeholder cond
Complete requests 1339 1395.9 1471.6
Requests per second 267.582 278.882 293.923


これはまぁ、どっち使ってもOKかな

「find」 VS 「find_by_sql」 VS 「named_scope」

  • 13カラムのモデルを使用(id, str1-5, int1-5, created_at, updated_at)
  • 計100レコード

下記表の項目定義

  • find: find(:all, :conditions => "id < 51 AND str1 = 'hoge'", :order => "id DESC", :limit => 10, :offset => 5)
  • sql: SELECT * FROM find_check10s WHERE id < 51 AND str1 = 'hoge' ORDER BY id DESC LIMIT 5, 10
  • ns all: named_scope で、all_in_one
    • Model.all_in_one
  • ns partial: named_scope で、ばらばら
    • Model.id_lt_51.str1_is_hoge.default_order.default_limit.default_offset

  find sql ns all ns partial
Complete requests 1753 1849.4 2313.6 2162.5
Requests per second 350.258 369.645 462.212 432.27


なぜ named_scope がこんなに良い結果になるのか。。。
find と find_by_sql は大して差は出ないらしい。