Upgrade to Pro — share decks privately, control downloads, hide ads and more …

複数DBとRails

Kohei Suzuki
November 10, 2014

 複数DBとRails

Rails複数DB Casual Talksで使ったスライドです
http://connpass.com/event/9560/

Kohei Suzuki

November 10, 2014
Tweet

More Decks by Kohei Suzuki

Other Decks in Programming

Transcript

  1. ෳ਺%#ͱ3BJMT
    ,PIFJ4V[VLJ !FBHMFUNU

    $PPLQBE*OD
    1

    View full-size slide

  2. Ξ΢τϥΠϯ
    ෳ਺%#Λ3BJMT͔Βѻ͏
    %#෼ׂ
    SXTQMJUUJOH
    ෳ਺%#τϥϒϧ
    ࠷ۙͷ೰Έ
    !2

    View full-size slide

  3. ෳ਺%#
    3BJMTͷόʔδϣϯΞοϓ
    Λ୲౰ͨ͠
    ಛʹ"DUJWF3FDPSEͷมߋʹରԠ͍ͯͨ͠Β3BJMT
    ʹ͓͚Δෳ਺%#ͱ޲͖߹͏͜ͱʹʜʜ
    !3

    View full-size slide

  4. ෳ਺%#ͷछྨ
    ͍͔ͭ͘छྨ͕͋Δ
    ୯ʹςʔϒϧ͕ผͷ%#ʹଘࡏ͍ͯ͠Δ %#෼ׂ

    NBTUFSTMBWFߏ੒ͰSXTQMJUUJOH͍ͯ͠Δ
    γϟʔσΟϯά
    γϟʔσΟϯά͸෼͔Βͳ͍ͷͰɺ্ͭʹ͍ͭͯ
    !4

    View full-size slide

  5. %#෼ׂ
    FTUBCMJTI@DPOOFDUJPOͰ઀ଓઌΛม͑Δ
    class Db1Model1 < ActiveRecord::Base
    establish_connection :"#{Rails.env}_db1"
    end
    !
    class Db1Model2 < ActiveRecord::Base
    establish_connection :"#{Rails.env}_db1"
    end
    !5

    View full-size slide

  6. %#෼ׂ
    ͜ΕͰ΋Ͱ͖Δ͚ͲɺίωΫγϣϯ਺͕ٸ૿͢Δ
    BQQ͸େৎ෉Ͱ΋%#͕଱͑ΒΕͳ͍
    !6

    View full-size slide

  7. "3ͷίωΫγϣϯ
    .PEFMDPOOFDUJPO͸ɺΫϥε֊૚Λ্Γͳ͕Β
    FTUBCMJTI@DPOOFDUJPO͍ͯ͠Δ࠷ॳͷϞσϧΫϥε
    ͷίωΫγϣϯϓʔϧΛ࢖͏
    ୯Ұ%#ͷͱ͖͸"DUJWF3FDPSE#BTFͷΈ
    ͢΂ͯͷϞσϧ͕"DUJWF3FDPSE#BTFͷίωΫ
    γϣϯϓʔϧΛ࢖͏
    !7

    View full-size slide

  8. "3ͷίωΫγϣϯ
    ֤ϞσϧͰͦΕͧΕFTUBCMJTI@DPOOFDUJPO͢Δͱɺ
    Ϟσϧͷ਺ʹൺྫͨ͠ίωΫγϣϯ͕࡞ΒΕΔ
    ਺ඦͷϞσϧ͕͋Δͱݱ࣮తͰ͸ͳ͍
    !8

    View full-size slide

  9. ίωΫγϣϯڞ༗
    FTUBCMJTI@DPOOFDUJPO͢Δ͚ͩͷந৅ΫϥεΛఆٛ
    ͢Δ
    class Db1Base < ActiveRecord::Base
    self.abstract_class = true
    establish_connection :"#{Rails.env}_db1"
    end
    !9

    View full-size slide

  10. ίωΫγϣϯڞ༗
    ECʹ͋Δςʔϒϧ Ϟσϧ
    ͸%C#BTFΛܧঝ͢
    ΔΑ͏ʹ͢Δ
    class Db1Model1 < Db1Base
    end
    !
    class Db1Model2 < Db1Base
    end
    !10

    View full-size slide

  11. ίωΫγϣϯڞ༗
    ίωΫγϣϯϓʔϧͷͨΊʹجఈΫϥε%C#BTFΛ
    ༻ҙ͢Δ
    ܧঝͨ͠%C.PEFM %C.PEFM͸%C#BTFͷ
    ίωΫγϣϯϓʔϧΛ࢖͏
    !11

    View full-size slide

  12. SXTQMJUUJOH
    ઀ଓઌΛ੾Γସ͍͑ͨͱ͖ʹFTUBCMJTI@DPOOFDUJPO͢Δ
    ϝϦοτ
    3BJMTඪ४ͷػೳ͚ͩͰͰ͖Δ
    σϝϦοτ
    FTUBCMJTI@DPOOFDUJPOͷ౓ʹ઀ଓ͠௚͢͜ͱʹͳΔ
    සൟͳ੾Γସ͑ʹ͸޲͔ͳ͍
    !12

    View full-size slide

  13. SXTQMJUUJOH
    !13
    class SummaryBase < ActiveRecord::Base
    self.abstract_class = true
    establish_connection :"#{Rails.env}_summary"
    !
    def self.with_master
    establish_connection :"#{Rails.env}
    _summary_writable"
    yield
    ensure
    establish_connection :"#{Rails.env}_summary"
    end
    end
    !
    !
    !

    View full-size slide

  14. SXTQMJUUJOH
    ίωΫγϣϯΛҡ࣋ͭͭ͠ɺසൟʹ੾Γସ͍͑ͨ
    Ϟσϧ͕ίωΫγϣϯϓʔϧΛछྨ͔࣋ͯ͠ͳ͍ͷ
    ͰɺϨʔϧ͔Β֎Εͳ͚Ε͹ͳΒͳ͍
    Ͱ͖Δ͚ͩඪ४తͳํ๏Ͱ࣮ݱ͢ΔͨΊʹ
    TXJUDI@QPJOUͱ͍͏HFNΛ࡞੒ͯ͠Ҡߦ
    IUUQTHJUIVCDPNFBHMFUNUTXJUDI@QPJOU
    !14

    View full-size slide

  15. SXTQMJUUJOH
    !15
    SwitchPoint.configure do |config|
    config.define_switch_point :main,
    readonly: :"#{Rails.env}_slave"
    !
    config.define_switch_point :bargain,
    readonly: :"#{Rails.env}_bargain_slave",
    writable: :"#{Rails.env}_bargain"
    !

    end

    View full-size slide

  16. SXTQMJUUJOH
    !16
    class MainBase < ActiveRecord::Base
    self.abstract_class = true
    use_switch_point :main
    end
    !
    class BargainBase < ActiveRecord::Base
    self.abstract_class = true
    use_switch_point :bargain
    end
    !
    class User < MainBase; end
    class Recipe < MainBase; end
    !
    class Bargain::Shop < BargainBase; end
    class Bargain::Leaflet < BargainBase; end

    View full-size slide

  17. SXTQMJUUJOH
    !17
    User.with_readonly { User.find(id) }
    !
    !
    Recipe.with_writable do
    Recipe.create(recipe_params)
    end

    View full-size slide

  18. ෳ਺%#τϥϒϧ

    View full-size slide

  19. %#Λލ͙+0*/
    Ϟσϧ"ɺ#͕ผͷ%#ʹ͋Δ
    "ͱ#͸+0*/Ͱ͖ͳ͍
    ͔͠͠ɺJODMVEFTΛ࢖ͬͨͱ͖ʹಛఆͷঢ়گԼͰ͸
    "DUJWF3FDPSEʹΑͬͯ+0*/͕࢖ΘΕͯ͠·͏
    !19

    View full-size slide

  20. %#Λލ͙+0*/
    !20
    class A < ActiveRecord::Base
    end
    !
    class B < ActiveRecord::Base
    belongs_to :a
    end
    irb(main):001:0> B.includes(:a).pluck(:id)
    (0.2ms) SELECT `bs`.`id` FROM `bs`
    LEFT OUTER JOIN `as` ON `as`.`id` = `bs`.`a_id`

    View full-size slide

  21. %#Λލ͙+0*/
    !21
    class A < ActiveRecord::Base
    end
    !
    class B < ActiveRecord::Base
    belongs_to :a
    end
    irb(main):001:0> B.preload(:a).pluck(:id)
    (0.2ms) SELECT `bs`.`id` FROM `bs`

    View full-size slide

  22. EBUBCBTF@SFXJOEFS
    EBUBCBTF@DMFBOFSʹ୅ΘΔHFN
    !BNBUTVEB͞Μ͕࡞ͬͨ
    This strategy was originally devised and implemented
    by Shingo Morita (@eudoxa) at COOKPAD Inc.
    IUUQTHJUIVCDPNBNBUTVEBEBUBCBTF@SFXJOEFSDSFEJU
    !22

    View full-size slide

  23. EBUBCBTF@SFXJOEFSͱෳ਺%#
    ෳ਺%#؀ڥͰ࠷ॳͷ%BUBCBTF3FXJOEFSDMFBO@BMM͕͏·͘ಈ͔
    ͳ͍໰୊
    "DUJWF3FDPSE#BTFҎ֎ͷίωΫγϣϯΛ͏·͘ͱΕͯͳ͍
    ࠷ऴతʹWͰղܾ
    IUUQTHJUIVCDPNBNBUTVEBEBUBCBTF@SFXJOEFSDPNQBSF
    WW
    TODO: Write documentation and specs about multiple databases.
    !23

    View full-size slide

  24. EBUBCBTF@SFXJOEFSͱෳ਺%#
    ෳ਺ͷ%#͕ҟͳΔBEBQUFSΛ࢖͍ͬͯΔͱ͖ʹςʔ
    ϒϧ͕ফ͞Εͳ͍໰୊
    .Z42-1PTUHSF42-ͳͲ
    !24

    View full-size slide

  25. EBUBCBTF@SFXJOEFSͱෳ਺%#
    EBUBCBTF@SFXJOEFSͷॳظԽ࣌ʹ͸·ͩผ%#ͷ
    BEBQUFS͕ಡΈࠐ·Ε͍ͯͳ͍͜ͱ͕ݪҼ
    IUUQTHJUIVCDPNBNBUTVEBEBUBCBTF@SFXJOEFSQVMM
    !25

    View full-size slide

  26. ࠷ۙͷ೰Έ

    View full-size slide

  27. ෳ਺%#ෳ਺ΞϓϦέʔγϣϯ
    ෳ਺ͷΞϓϦέʔγϣϯ͕ϞσϧΛڞ༗͍ͯ͠Δ
    DPPLQBEDPNຊମ
    8FC"1*αʔό
    ؅ཧը໘
    όον
    !27

    View full-size slide

  28. ෳ਺%#ෳ਺ΞϓϦέʔγϣϯ
    ͢΂ͯͷΞϓϦέʔγϣϯ͕͢΂ͯͷ%#ʹ઀ଓ͢Δ
    Θ͚Ͱ͸ͳ͍
    ؅ཧը໘͔Β͔͠࢖ΘΕͳ͍%#
    ؅ཧը໘ͱόον͔Β͔͠࢖ΘΕͳ͍%#
    ʜʜ
    !28

    View full-size slide

  29. ෳ਺%#ෳ਺ΞϓϦέʔγϣϯ
    Ϟσϧ͸֤ΞϓϦέʔγϣϯͰڞ༗͞Ε͍ͯΔ
    ҰํͰɺͦͷΞϓϦέʔγϣϯ͔Β࣮ࡍʹ͸࢖ΘΕͳ
    ͍%#ͷ઀ଓઃఆΛEBUBCBTFZNMʹॻ͖ͨ͘ͳ͍
    ྫ͑͹όον͔Β͔͠࢖ΘΕͳ͍%#Λߋ৽ͨ࣌͠ʹɺ
    8FC"1*αʔόʹ΋EBUBCBTFZNMΛ഑෍͢Δඞཁ
    ͕͋ΔΑ͏ͳঢ়گ͸ආ͚͍ͨ
    !29

    View full-size slide

  30. ෳ਺%#ෳ਺ΞϓϦέʔγϣϯ
    Ϟσϧ͕ڞ༗͞Ε͍ͯΔͷͰɺىಈ࣌ʹ
    EBUBCBTFZNMʹॻ͔Ε͍ͯͳ͍%#΁ͷ
    FTUBCMJTI@DPOOFDUJPO͕࣮ߦ͞Εͯ͠·͏
    "DUJWF3FDPSE"EBQUFS/PU4QFDJpFEΛѲΓ௵͢Ϟ
    ϯΩʔύον
    ඇৗʹͭΒ͍ʜʜԿ͔ྑ͍ํ๏͕͋Ε͹ੋඇ
    !30

    View full-size slide