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

ActiveRecordデータ処理アンチパターン / active-record-anti-patterns

ActiveRecordデータ処理アンチパターン / active-record-anti-patterns

Rails Developers Meetup 2018: Day 2( https://techplay.jp/event/655769 )で行った発表の資料です。

ActiveRecordはWebエンジニア達が嫌う(?)SQLを書かずとも、Rubyオブジェクトで気軽にデータベースへアクセスできる魔法のようなツールです。しかし便利な反面、何も考えずにゴリゴリActiveRecordを使ってDBアクセスしていると、劇的に重たいクエリが発行されたり非効率的なクエリが量産されたりします。

本発表ではそれらActiveRecordで陥りがちな罠をパターン化し、ActiveRecordデータ処理アンチパターンとして発表します。

※発表では実際のサンプルコードとともにパフォーマンスの計測結果も紹介します。

---

Blog記事: http://blog.toshimaru.net/rdm2018-active-record-anti-patterns/

toshimaru

March 25, 2018
Tweet

More Decks by toshimaru

Other Decks in Technology

Transcript

  1. "DUJWF3FDPSEσʔλॲཧ
    Ξϯνύλʔϯ

    3BJMT%FWFMPQFST.FFUVQ

    View Slide

  2. ࣗݾ঺հ
    • ӿຊ හؙʢtoshimaruʣ

    • Twitter: @toshimaru_e/Github: toshimaru

    • Rails Engineer ˏגࣜձࣾGunosy

    • ࠷ۙͷਪ͠gem:

    • toshimaru/rubocop-rails
    2

    View Slide

  3. ࠓ೔࿩͢͜ͱ ߦͰ

    ̏ͭͷࣄྫΛ΋ͱʹ̒ͭͷ"DUJWF3FDPSEσʔλ
    ॲཧʹ͓͚ΔΞϯνύλʔϯΛίʔυͱͦͷϕ
    ϯνϚʔΫ݁Ռͱ΋ʹ঺հ͠·͢ɻ
    3

    View Slide

  4. ຊൃදͷΰʔϧ
    "DUJWF3FDPSEΛ࢖ͬͨඇޮ཰ͳσʔλॲཧʹΑͬͯύϑΥʔ
    Ϛϯε͕ܶతʹམͪΔ͜ͱ͕͋Δ͜ͱΛཧղ͢Δ
    ຊൃදͰ঺հ͢ΔΞϯνύλʔϯΛਖ਼͘͠ཧղ͠Ξϯνύ
    λʔϯΛ౿ΜͩίʔυΛमਖ਼͢Δ͜ͱ͕Ͱ͖Δɻ΋͘͠͸
    ΞϯνύλʔϯΛճආͨ͠ίʔυΛॻ͘͜ͱ͕Ͱ͖Δ
    ίʔυϨϏϡʔʹ͓͍ͯΞϯνύλʔϯΛ౿ΜͩίʔυΛ
    ൃݟɾࢦఠ͢Δ͜ͱ͕Ͱ͖Δ
    4

    View Slide

  5. 8IZOPU42-
    w ʮͦΕ42-ͰͰ͖ΔΑʯ
    w ύϑΥʔϚϯεϑΝʔετͰٕज़બ୒͢ΔͷͰ͋Ε͹ۃ࿦/P
    03. /P3VCZ͕ϕετ
    w ͳͥ"DUJWF3FDPSEʹͩ͜ΘΔ͔ʁ
    w %#ͱͷΠϯλϥΫγϣϯΛ"DUJWF3FDPSEϞσϧʹू໿͠ڽू
    ౓ͷߴ͍ϞσϧΛߏங͢Δ
    w 'MFYJCJMJUZ ॊೈੑ
    .FJOUFOBCJMJUZ ϝϯςφϯεੑ

    3FBEBCJMJUZ Մಡੑ

    5

    View Slide

  6. ϕϯνϚʔΫ
    w ϕϯνϚʔΫ͸Լه63-ͷίʔυΛࢀߟʹॲཧͷ࣮ߦ࣌ؒͱϝϞϦ࢖༻ྔΛ
    ܭଌ
    w IUUQTEBMJCPSOBTFWJDDPNQPTUTQSPDFTTJOHMBSHFDTWpMFTXJUISVCZ
    w ϕϯνϚʔΫ؀ڥ
    w $JSDMF$* $16.#
    ্Ͱܭଌ
    w 3VCZ3BJMT.Z42-
    w ιʔείʔυɾϕϯνϚʔΫ݁Ռ͸ެ։͞Ε·͢
    w IUUQTHJUIVCDPNUPTIJNBSVSENSBJMT
    6

    View Slide

  7. લఏࣄ߲
    w ࠓճίʔυ಺Ͱొ৔͢ΔϞσϧ͸6TFSIBTNBOZ1PTUTͳؔ
    ܎ͷ6TFSϞσϧ1PTUϞσϧ
    w ࣄલʹ6TFSສ݅ɺ1PTU໿ສ݅Λσʔλͱͯ͠ొ࿥
    w ϢʔβʔͷλΠϜκʔϯ͸શͯ65$ͱͯ͠ѻ͏
    w ࠓճߦ͏࠷దԽͷର৅͸ΞϓϦέʔγϣϯίʔυͰ͋Γɺ
    σʔλϕʔεͷ࠷దԽ͸ߟ͑ͳ͍
    w σʔλϕʔεͷτϥϯβΫγϣϯॲཧ͸ߟྀ͠ͳ͍
    7

    View Slide

  8. εΩʔϚఆٛ TDIFNBSC

    8

    View Slide

  9. ࣄྫ̍
    શϢʔβʔͷத͔Β೥Ҏ߱ͷొ࿥Ϣʔβʔ΁ϙΠ
    ϯτΛ෇༩͢Δɻ
    9
    ˞ొ࿥೔6TFSDSFBUFE@BUͱͯ͠ѻ͍·͢

    View Slide

  10. ΦϦδφϧιʔείʔυ
    10

    View Slide

  11. ΦϦδφϧίʔυ
    ϕϯνϚʔΫ
    11
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#

    View Slide

  12. -PPLT(PPE5P:PV
    12

    View Slide

  13. All Each Pattern
    13
    Anti-Pattern

    View Slide

  14. "MM&BDI1BUUFSO
    w .PEFMBMMͰ͋ΔςʔϒϧͷશϨίʔυΛऔಘͨ͠ޙʹɺ
    ͦͷ݁ՌΛFBDIͰϧʔϓͤ͞Δ͜ͱ
    14

    View Slide

  15. "MM&BDI1BUUFSO໰୊఺
    w શ݅औಘͰϝϞϦ͕ඡഭ
    w ͦ΋ͦ΋શ݅औಘͰ͋Δඞཁ͕͋Δͷ͔ʁ
    w ୯७ʹϧʔϓճ਺͕૿͑ΔͷͰ$16Ϧιʔε΋ফඅ
    15

    View Slide

  16. "MM&BDI1BUUFSOղܾࡦ
    6TFSऔಘ݅਺ΛϑΟϧλʔ
    w BMM➜XIFSF
    গͣͭ͠6TFSΛऔಘͯ͠ϝϞϦϑϨϯυϦʔͳॲཧʹ
    w FBDI➜pOE@FBDI
    16

    View Slide

  17. վળޙιʔείʔυ
    17

    View Slide

  18. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    18
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ TFDT .#

    View Slide

  19. 19
    -PPLT(PPE5P:PV

    View Slide

  20. N+1 Update Queries Pattern
    20
    Anti-Pattern

    View Slide

  21. /6QEBUF2VFSJFT1BUUFSO
    21
    1 Select
    N Update

    View Slide

  22. /6QEBUF2VFSJFT1BUUFSO
    ໰୊఺
    w ճ4FMFDU/ճ6QEBUFͷΫΤϦ͕૸Δ
    w /ͷ਺͕ଟ͘ͳΕ͹ͳΔ΄ͲύϑΥʔϚϯε͕ѱԽ
    w ؔ࿈Ξϯνύλʔϯ
    w /%FMFUF1BUUFSO
    22

    View Slide

  23. /6QEBUF2VFSJFT1BUUFSO
    ղܾࡦ
    ෳ਺ϨίʔυΛҰׅͰߋ৽͢Δ
    w VQEBUF➜VQEBUF@BMM
    23

    View Slide

  24. վળޙιʔείʔυ
    24

    View Slide

  25. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    25
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ TFDT .#
    վળ̎ TFDT .#

    View Slide

  26. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    26
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ TFDT .#
    վળ̎ TFDT .#
    ࣄྫ̍݁Ռ
    ࣮ߦ࣌ؒ͸ഒҎ্ߴ଎ԽɺϝϞϦফඅ΋෼ͷఔ౓·
    Ͱ཈͑Δ͜ͱ͕Ͱ͖·ͨ͠ɻ

    View Slide

  27. ஫ҙ఺
    w VQEBUFͱVQEBUF@BMMͷॲཧ͸౳ՁͰ͸ͳ͍
    w JUEPFTOPUUSJHHFS"DUJWF3FDPSEDBMMCBDLTPSWBMJEBUJPOT
    w ݱ৔ʹ͓͍ͯ͸ద੾ͳॲཧΛՃ্͑ͨͰVQEBUF@BMMΛ࢖͏͜
    ͱ
    w ςʔϒϧϩοΫʹ஫ҙʂ
    w ద੾ͳτϥϯβΫγϣϯઃఆɾϩοΫͷઃఆΛʂ
    w গͣͭ͠VQEBUF@BMMJO@CBUDIFTVQEBUF@BMM
    27

    View Slide

  28. ࣄྫ̎
    Ϣʔβʔຖͷهࣄͷ͍͍Ͷ਺ʢMJLF@DPVOUʣ߹ܭ͕ଟ͍ॱͰ
    501ϢʔβʔͷϢʔβʔ໊Λ߹ܭ͍͍Ͷ਺ͱͱ΋ʹग़ྗ
    ͢Δɻ
    28
    ˞࣮ࡍ͸ԿΒ͔ͷσʔλετΞʹอଘ͢Δॲཧ͕૝ఆ͞ΕΔ͕ࠓճ͸γϯϓϧʹඪ
    ४ग़ྗͱ͢Δ

    View Slide

  29. 29
    ΦϦδφϧιʔείʔυ

    View Slide

  30. ΦϦδφϧίʔυ
    ϕϯνϚʔΫ
    30
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#

    View Slide

  31. 31
    -PPLT(PPE5P:PV

    View Slide

  32. Ruby Aggregation Pattern
    32
    Anti-Pattern

    View Slide

  33. 3VCZ"HHSFHBUJPO1BUUFSO
    w Ϩίʔυશऔಘɺ3VCZͷੈքͰूܭɾฒͼସ͑
    33

    View Slide

  34. 3VCZ"HHSFHBUJPO1BUUFSO
    ໰୊఺
    w طʹ঺հͨ͠ԼهͷΞϯνύλʔϯΛ౿ΜͰ͍Δ
    w "MM&BDI1BUUFSO
    w ϝϞϦϦιʔεʹՃ͑ɺ$16Ϧιʔε΋ແବʹফඅ
    34

    View Slide

  35. 3VCZ"HHSFHBUJPO1BUUFSO
    ղܾࡦ
    w ૉ௚ʹ3%#ͷू໿ɾूܭؔ਺Λ࢖͍·͠ΐ͏
    w <3VCZ>TPSU@CZSFWFSTF➜<42->PSEFS
    w <3VCZ>UBLF➜<42->MJNJU
    w <3VCZ>QPTUTTVN MJLF@DPVOU
    ➜<42->
    HSPVQ VTFS@JE
    TFMFDU l46. MJLF@DPVOU
    z

    35

    View Slide

  36. վળޙιʔείʔυ
    36

    View Slide

  37. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    37
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ TFDT .#

    View Slide

  38. 38
    -PPLT(PPE5P:PV

    View Slide

  39. N+1 Queries Pattern
    39
    Anti-Pattern

    View Slide

  40. 40
    N+1
    /2VFSJFT1BUUFSO
    w ৄ͍͠આ໌͸লུ
    w 3BJMTॳ৺ऀ͕࠷΋౿Έ΍͍͢ύλʔϯ

    View Slide

  41. /2VFSJFT1BUUFSOղܾࡦ
    w ϞσϧʹJODMVEFTΛ෇༩
    w ʲ5JQTʳKPJOT JODMVEFT QSFMPBE FBHFS@MPBEͷҧ͍Λҙࣝ
    ͯ͠࢖͍෼͚ΒΕΔͱϕετ
    w SFG"DUJWF3FDPSEͷKPJOTͱQSFMPBEͱJODMVEFTͱ
    FBHFS@MPBEͷҧ͍
    41

    View Slide

  42. վળޙιʔείʔυ
    42

    View Slide

  43. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    43
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ̍ TFDT .#
    վળ̎ TFDT .#

    View Slide

  44. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    44
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ̍ TFDT .#
    վળ̎ TFDT .#
    ࣄྫ̎݁Ռ
    ࣮ߦ࣌ؒ͸໿ഒߴ଎ԽɺϝϞϦফඅ΋෼ͷҎԼ·Ͱ
    ཈͑Δ͜ͱ͕Ͱ͖·ͨ͠ɻ

    View Slide

  45. ࣄྫ̏
    Ϣʔβʔຖͷهࣄͷ͍͍Ͷ਺ʢMJLF@DPVOUʣ߹ܭ͕ଟ͍ॱͰ
    501ϢʔβʔͷϢʔβʔ*%ҰཡΛग़ྗ͢Δɻ
    45
    ˞Ϣʔβʔ*%Ұཡ͸"SSBZͷܗࣜͰඪ४ग़ྗͰ͖ͯΕ͹Α͠ͱ͢Δ

    View Slide

  46. 46
    ΦϦδφϧιʔείʔυ

    View Slide

  47. ΦϦδφϧίʔυ
    ϕϯνϚʔΫ
    47
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#

    View Slide

  48. 48
    -PPLT(PPE5P:PV

    View Slide

  49. Unnecessary Query Pattern
    49
    Anti-Pattern

    View Slide

  50. 6OOFDFTTBSZ2VFSZ1BUUFSO
    ໰୊఺
    w ຊདྷඞཁͰ͸ͳ͍ϦιʔεΛऔಘ͍ͯ͠Δ͜ͱ
    w ແବͳ42-ൃߦɾϝϞϦফඅ͕ൃੜ
    50

    View Slide

  51. 6OOFDFTTBSZ2VFSZ1BUUFSO
    ղܾࡦ
    w ෆඞཁͳࢀরΛ࡟আ
    w QPTUVTFSJE➜QPTUVTFS@JE
    51

    View Slide

  52. վળޙιʔείʔυ
    52

    View Slide

  53. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    53
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ TFDT .#

    View Slide

  54. 54
    -PPLT(PPE5P:PV

    View Slide

  55. Unnecessary Model
    Initialization Pattern
    55
    Anti-Pattern

    View Slide

  56. w ෆඞཁͳ"DUJWF3FDPSEϞσϧͷੜ੒͕ൃੜ
    w "DUJWF3FDPSEͷϞσϧੜ੒ίετ͸ۃΊͯߴ͍
    w "3ϞσϧΛੜ੒͠ͳͯ͘ࡁΉͷͰ͋Ε͹ɺͦΕʹӽ͠
    ͨ͜ͱ͸ͳ͍
    6OOFDFTTBSZ.PEFM*OJU1BUUFSO
    ໰୊఺
    56

    View Slide

  57. 6OOFDFTTBSZ.PEFM*OJU1BUUFSO
    ղܾࡦ
    w "DUJWF3FDPSEϞσϧΛੜ੒ΛӌճͰ͖ΔϝιουΛ࢖༻
    w TFMFDU➜QMVDL
    57

    View Slide

  58. վળޙιʔείʔυ
    58

    View Slide

  59. վળޙιʔείʔυ
    ϕϯνϚʔΫ
    59
    5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ̍ TFDT .#
    վળ̎ TFDT .#

    View Slide

  60. 5JNF .FNPSZ
    ΦϦδφϧ TFDT .#
    վળ̍ TFDT .#
    վળ̎ TFDT .#
    վળޙιʔείʔυ
    ϕϯνϚʔΫ
    60
    ࣮ߦ࣌ؒɺϝϞϦফඅͱ΋ʹఔ౓·Ͱվળ͢Δ͜ͱ͕Ͱ
    ͖·ͨ͠ɻ
    ࣄྫ̏݁Ռ
    60

    View Slide

  61. "OUJ1BUUFSOT
    "MM&BDI1BUUFSO
    /6QEBUF2VFSJFT1BUUFSO
    3VCZ"HHSFHBUJPO1BUUFSO
    /2VFSJFT1BUUFSO
    6OOFDFTTBSZ2VFSZ1BUUFSO
    6OOFDFTTBSZ.PEF*OJUJBMJ[BUJPO1BUUFSO
    61

    View Slide

  62. ·ͱΊ
    w "DUJWF3FDPSE͸ॾਕͷ݋
    w ਖ਼͘͠࢖͑͹ڧྗͳπʔϧͰ͋ΔҰํɺޡͬͨ࢖͍ํΛ
    ͢ΔͱϘτϧωοΫΛ࡞Γग़͠΍͍͢
    w ීஈ͔ΒΫΤϦϩάΛோΊͯσʔλϕʔεͷύϑΥʔϚϯ
    εΛҙࣝͯ͠ίʔυΛॻ͘श׳Λ͚ͭΔ
    w ίʔυϨϏϡʔ΋ಉ༷
    62

    View Slide

  63. ͱ͸͍͑
    w Ұൠతʹσʔλϕʔεͷ࠷దԽͷํ͕γεςϜશମʹޮ͘
    ൚༻తͳղܾࡦͱͳΓ΍͍͢
    w σʔλϕʔεͷ࠷దԽΛ·ͣ͸ݕ౼ͦ͠ΕΛߦ্ͬͨͰΞ
    ϓϦέʔγϣϯίʔυͷ࠷దԽΛߦ͏͜ͱ
    w SFGʰ42-Ξϯνύλʔϯʱ
    63

    View Slide

  64. "DUJWF3FDPSEΛਖ਼͘͠࢖͍͜ͳͯ͠
    ΑΓྑ͍"DUJWF3FDPSEϥΠϑΛʂ
    64

    View Slide

  65. Thank You
    65

    View Slide