Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

Slide 4

Slide 4 text

ISUCON͍ۙͰ͢Ͷ

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Slide 8

Slide 8 text

෮शʣN + 1ͱ͸ʁ

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

͜ΕΛ࣮ߦ͢Δͱ… @memos = Memo.all @memos.each do |memo| memo.id memo.user.name end

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Rails࢖ͬͯΔͱɺ
 N + 1Λ؆୯ʹղফͰ͖·͢ΑͶ

Slide 13

Slide 13 text

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ʹͳΔ

Slide 14

Slide 14 text

includesͱ͔eager_loadͱ͔ ৭ʑ͋Γ·͢ΑͶ

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

AssociationͷΩϟογϡ͸
 ສೳ͔??

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

ؔ࿈ઌςʔϒϧͷΧϥϜΛ࡟আ ͍ͨ͠ͱ͢Δ • લఏ৚݅ • ↓ͷίʔυ͕ଘࡏ͢Δ • ΞϓϦέʔγϣϯίʔυ͔Βɺ 
 deprecated_columnΛࢀর͠ͳ͍Α͏ʹमਖ਼ࡁΈ @memos = Memo.includes(:user).where(users: { name: ‘horikawa’ }) @memos.each do |memo| memo.id memo.user.name end

Slide 21

Slide 21 text

౴͑ • ؔ࿈ςʔϒϧͷΩϟογϡΛऔಘ͢Δࡍʹɺ
 શͯͷΧϥϜ৘ใΛSELECTจͰࢦఆͨ͠ΫΤϦΛൃߦ͠Α͏ͱ͢Δ (SELECT … `users`.`id` AS t1_r0, `users`.`deprecated_column` AS t1_r1)
 ↓ • ϚΠάϨʔγϣϯͰɺΧϥϜΛ࡟আ͢Δ
 ˣ • ΫΤϦΛ࣮ߦ͢ΔࡍʹɺΩϟογϡΛ࢖͏ͷͰɺ
 ଘࡏ͠ͳ͍ΧϥϜʹର͢ΔΞΫηεΛͯ͠ɺΤϥʔ͕ग़Δ

Slide 22

Slide 22 text

౴͑ # 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

Slide 23

Slide 23 text

ରࡦ

Slide 24

Slide 24 text

Rails 5.xͰ͋Ε͹ • ignored_columnsΛ࢖͓͏ʂ • εΩʔϚ৘ใʹՃ͑ͳ͍Α͏ʹͯ͘͠ΕΔ • User.column_namesͰ
 deprecated_column͕ग़ͳ͚Ε͹͓k class User < ApplicationRecord self.ignored_columns = %w(deprecated_column) end

Slide 25

Slide 25 text

ਖ਼͍͠σϓϩΠॱ • deprecated_columnΛࢀর͢ΔίʔυΛ࡟আ͢ Δ
 ˣ • ignored_columnʹdeprecated_columnΛ௥Ճ
 ˣ • ΧϥϜΛ࡟আ

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

Rails ্͛Α͏

Slide 28

Slide 28 text

ࢀߟ • 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