Caching associations in rails

Ecf4ad5c20312b8499a615263519290a?s=47 horikawa
August 14, 2019

Caching associations in rails

Ecf4ad5c20312b8499a615263519290a?s=128

horikawa

August 14, 2019
Tweet

Transcript

  1. AssociationͷΩϟογϡ͸
 ӡ༻ʹؾΛ͚ͭͯ (Otemachirb#20) גࣜձࣾπΫϧόɹαʔόαΠυΤϯδχΞ ງ઒ɹ@CASIXx1  

  2. • ීஈ͸ʮcowcamoʯͱ͍͏ΞϓϦΛ։ൃͯ͠ ·͢ • αʔόαΠυ͸ɺRailsʢ5.2ʣΛ࢖ͬͯ·͢  

  3.  

  4. ISUCON͍ۙͰ͢Ͷ  

  5. ISUCONͷաڈ໰
 ΍ͬͯΔͷͰ͕͢  

  6. N + 1໰୊͸
 ఆ൪Ͱ͢ΑͶɻɻɻ  

  7.  

  8. ෮शʣN + 1ͱ͸ʁ  

  9. ҎԼͷϞσϧ͕͋ͬͨ৔߹   app/models/user.rb class User < ApplicationRecord has_many :memos

    end app/models/memo.rb class Memo < ApplicationRecord belongs_to :user end
  10. ͜ΕΛ࣮ߦ͢Δͱ…   @memos = Memo.all @memos.each do |memo| memo.id

    memo.user.name end
  11. N + 1͕ൃੜ͢Δ N(memo.userͷ਺) + 1(Memo.allͷΞΫηε) SELECT 'memos'.* FROM 'memos'

    # Memo.allͷΞΫηε # memo.user.nameͷΞΫηε SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 1 LIMIT 1 SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 2 LIMIT 1 SELECT 'users'.* FROM 'users' WHERE 'users'.'id' = 3 LIMIT 1  
  12. Rails࢖ͬͯΔͱɺ
 N + 1Λ؆୯ʹղফͰ͖·͢ΑͶ  

  13. includes, preload, eager_load Λ࢖͑͹ྑ͍   @memos = Memo.all.includes(:user) @memos.each

    do |memo| memo.id memo.user.name end SELECT 'memo'.* FROM 'memos' SELECT 'users'.* FROM 'users' WHERE 'users'.'id' IN (1, 2, 3) N + 1→1 + 1ʹͳΔ
  14. includesͱ͔eager_loadͱ͔ ৭ʑ͋Γ·͢ΑͶ  

  15. N + 1ΛղܾͰ͖Δ͔൱͔ • N + 1ΛղܾͰ͖ͳ͍ • joins •

    N + 1ΛղܾͰ͖Δʢؔ࿈ςʔϒϧ৘ใΛؚΊͯΩϟογϡ͢Δʣ • eager_load • LEFT OUTER JOINΛར༻͢Δʢt0_r0Έ͍ͨͳ΍ͭʣ • preload • IN۟Λར༻ͯ͠ɺෳ਺ΫΤϦͰऔͬͯ͘Δ • whereͰؔ࿈ςʔϒϧͷ৘ใΛߜΕͳ͍ • includes • eager_load, preloadΛঢ়گʹԠͯ͡ɺ࢖͍෼͚͢Δ  
  16. AssociationͷΩϟογϡ͸
 ສೳ͔??  

  17. ύϑΥʔϚϯεతʹ
 ؾΛ͚ͭͳ͚Ε͹ͳΒͳ͍࿩΋͋ΔΒ͍͕͠…  

  18. ӡ༻໘Ͱ΋ؾΛ͚ͭͳ͍ͱ͍͚ͳ͍ʂ  

  19. ؔ࿈ઌςʔϒϧͷΧϥϜΛ
 ࡟আ͍ͨ͠ͱ͢Δ • UserςʔϒϧͰɺ࡟আ͍ͨ͠ΧϥϜ͕͋Δͱ͢Δ • Ծʹɺ deprecated_columnͱ͍͏໊લʹ͠·͢ • Α͠ʂΧϥϜ࡟আ͢Δ
 ϚΠάϨʔγϣϯΛ͔͚Α͏ʂ

    • ͔͠͠ɺΤϥʔ͕ग़ͯ͠·͍·ͨ͠ɻ
 ԿނͰ͠ΐ͏ʁʁ  
  20. ؔ࿈ઌςʔϒϧͷΧϥϜΛ࡟আ ͍ͨ͠ͱ͢Δ • લఏ৚݅ • ↓ͷίʔυ͕ଘࡏ͢Δ • ΞϓϦέʔγϣϯίʔυ͔Βɺ 
 deprecated_columnΛࢀর͠ͳ͍Α͏ʹमਖ਼ࡁΈ

      @memos = Memo.includes(:user).where(users: { name: ‘horikawa’ }) @memos.each do |memo| memo.id memo.user.name end
  21. ౴͑ • ؔ࿈ςʔϒϧͷΩϟογϡΛऔಘ͢Δࡍʹɺ
 શͯͷΧϥϜ৘ใΛSELECTจͰࢦఆͨ͠ΫΤϦΛൃߦ͠Α͏ͱ͢Δ (SELECT … `users`.`id` AS t1_r0, `users`.`deprecated_column`

    AS t1_r1)
 ↓ • ϚΠάϨʔγϣϯͰɺΧϥϜΛ࡟আ͢Δ
 ˣ • ΫΤϦΛ࣮ߦ͢ΔࡍʹɺΩϟογϡΛ࢖͏ͷͰɺ
 ଘࡏ͠ͳ͍ΧϥϜʹର͢ΔΞΫηεΛͯ͠ɺΤϥʔ͕ग़Δ  
  22. ౴͑   # whereͰ৚݅෼ذ͢Δͱɺleft outer joinͰΩϟογϡΛੜ੒͢Δ @memos = Memo.includes(:user).where(users:

    { name: ‘horikawa’ }) # ॲཧ͕͜͜Βลʹ͍ΔλΠϛϯάͰɺΧϥϜΛ࡟আ͞Εͯ͠·͏ͱ… # memo.deprecated_column͕ͳ͍ͱΤϥʔ͕ग़Δ @memos.each do |memo| memo.id memo.user.name end
  23. ରࡦ  

  24. Rails 5.xͰ͋Ε͹ • ignored_columnsΛ࢖͓͏ʂ • εΩʔϚ৘ใʹՃ͑ͳ͍Α͏ʹͯ͘͠ΕΔ • User.column_namesͰ
 deprecated_column͕ग़ͳ͚Ε͹͓k 

     class User < ApplicationRecord self.ignored_columns = %w(deprecated_column) end
  25. ਖ਼͍͠σϓϩΠॱ • deprecated_columnΛࢀর͢ΔίʔυΛ࡟আ͢ Δ
 ˣ • ignored_columnʹdeprecated_columnΛ௥Ճ
 ˣ • ΧϥϜΛ࡟আ

     
  26. ͪͳΈʹRails 4.xͰ͋Ε͹ • ActiveRecord::Base.columnsΛΦʔόʔϥΠ υͯ͠ɺ
 deprecated_columnΛreject͢Δඞཁ͕͋Δ Έ͍ͨͰ͢  

  27. Rails ্͛Α͏  

  28. ࢀߟ • https://moneyforward.com/engineers_blog/2019/04/02/ activerecord-includes-preload-eagerload/ • https://dev.classmethod.jp/server-side/activerecord-join/ • https://qiita.com/ykamez/items/0c81a33ec1b90219d541 • https://qiita.com/SoarTec-lab/items/

    a192d381323cb741538e • https://eagletmt.hateblo.jp/entry/2017/09/24/004709