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
$ 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 1 | slct 1 | all 10 | slct 10 | all 100 | slct 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 1 | slct 1 | all 10 | slct 10 | all 100 | slct 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 のマルチカラムインデックス
- 計100レコード
下記表の項目定義
- find_by: find_all_by_str1('hoge')
- cond placeholder: find(:all, :conditions => ["str1 = ?", "hoge"])
- プレースホルダー使用
- cond: find(:all, :conditions => "str1 = 'hoge'")
- プレースホルダー未使用
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 は大して差は出ないらしい。