

Railsアプリでのパフォーマンス改善対応を行っています。  
よくあるパターンですが、ループ内にModelから取ったクラス変数があると  
アクセスのたびにSQL発行してパフォーマンス劣化するということがありますが  
これの改善策ってあったりしますでしょうか？  
N+1ならincludesでeager loadするのが定石だと思いますが、  
これとは別に対策するにはどのような方法がありますでしょうか？  
どうかよろしくお願いします。

［追記］ソースを付記します  
controller

[code]

      def ratings(args)
        @ratings = rating_response[:body]['items'].uniq { |rating| rating['work_id'] }.sort { |a, b| b['rating'] <=> a['rating'] }
        work_ids = @ratings.map { |rating| rating['work_id'] }
        @works = Work.where(resource_id: work_ids)
        render
      end
    
[/code]

view

[code]

       tbody
          - @ratings.each do |rating|
            - work = @works.find_by(resource_id: rating["work_id"])
            - if work.blank?
              - next
            tr
              td
                = link_to work.resource_id, "https://#{somedomain}/#{work.resource_id}/", target: '_blank'
              td
    
[/code]

特にModel同士でRelation組んだりとかして無く、@work.find_byがいけないのか

[code]

    [1] pry(#<#<Class:0x007f6e150166b8>>)> n
      Work Load (26.4ms)  SELECT  `works`.* FROM `works` WHERE `works`.`resource_id` IN (12652, 19584, 52842, 13079, 61785, 24657, 17732, 62705, 58215, 25900, 41473, 26710, 17522, 16348, 62092, 24517, 28466, 22101, 52609, 61766, 61219, 58327, 24796, 22172, 53589, 35546, 19453, 25870, 35378, 17434, 56209, 47797, 27907, 41119, 63235, 17524, 17523, 17515, 62706, 60183, 63448, 50583, 33323, 93564, 59342, 20553, 49100, 59704, 61684, 14470, 56308, 60890, 11649, 54247, 42777, 17609, 32642, 63302, 62415, 62309, 63078, 38673, 17525, 17521, 17519, 17517, 17516, 38057, 10905, 31822, 17527, 29125, 27717, 26746, 48703, 51970, 30309, 29680, 31142, 52149, 23952, 25197, 17109, 56878, 14035, 23756, 93082, 93052, 93053, 61057, 57613, 59634, 43869, 13433, 14526, 23403, 19164, 23624, 52856, 52060, 17425, 11240, 18880, 58425, 10349, 10373, 62534, 63307, 20408, 58943, 62864, 51122, 17424, 17436, 54246, 24997, 51535, 29782, 61265, 60674, 23782, 30903, 18067, 39484, 34789, 29829, 21785, 57837, 25784, 61068, 42482, 34673, 61003, 61059, 35486, 21203, 38659, 21787, 47059, 63044, 15095, 33392, 52875, 62759, 41627, 60398, 59114, 44762, 17520, 17518, 17514, 27147, 63500, 16577, 19234, 61097, 62607, 93572, 50630, 63480) AND `works`.`resource_id` = 19584 LIMIT 1
    
[/code]

みたいな感じでselectが発行されます。なんでなんでしょう？最初に一回selectかけるだけで、あとはそこから都度取得というのが望ましいと考えています。可能でしょうか？


CC BY-SA 3.0
2018-02-02T02:02:44.137
41395
2018-02-06T10:55:24.137
2018-02-05T06:01:35.920
4784
4784
question
ruby-on-rails
Railsアプリのパフォーマンス改善策でSQL発行回数を減らすには？


ビューを

[code]

    @works.each do |work|
       ：
    
[/code]

のループにすればいいのではないでしょうか。

今のコードはループの中で都度

[code]

    Work.where(resource_id: work_ids).find_by(resource_id: ...)
    
[/code]

を呼んでいるのと同じ意味になります。


CC BY-SA 3.0
2018-02-06T10:55:24.137
41514
2018-02-06T10:55:24.137
5793
41395
answer