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

そのpreloadは必要?見過ごされたpreloadが技術的負債として爆発した日

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for mugi mugi
September 27, 2025

 そのpreloadは必要?見過ごされたpreloadが技術的負債として爆発した日

Kaigi on Rails 2025

Avatar for mugi

mugi

September 27, 2025
Tweet

Other Decks in Programming

Transcript

  1. 自己紹介 1 麦倉 柊太(Shuta Mugikura) / mugi ⚫ X: @mugi_1359

    ⚫ GitHub: @mugitti9 ⚫ Kaigi on Rails オーガナイザー ⚫ 株式会社ギフティ
  2. preloadのメモリコスト 11 Article ID: 1 Article ID: 2 Article ID:

    3 SELECT * FROM comments WHERE article_id IN (1, 2, 3) Article.pluck(:id) SELECT * FROM likes WHERE comment_id IN (1, 2, 3, ...)
  3. preloadのメモリコスト 12 Article ID: 1 Comment ID: 1 Comment ID:

    2 Comment ID: 3 Article ID: 2 Comment ID: 4 Comment ID: 5 Comment ID: 6 Article ID: 3 Comment ID: 7 Comment ID: 8 Comment ID: 9 Like ID: 1 Like ID: 2 Like ID: 3 Like ID: 4 Like ID: 5 Like ID: 6 Like ID: 7 Like ID: 8 Like ID: 9 Like ID: 10 Like ID: 11 Like ID: 12 Like ID: 13 Like ID: 14 Like ID: 15 Like ID: 16 Like ID: 17 Like ID: 18
  4. preloadのメモリコスト 13 Article ID: 1 Article ID: 2 Article ID:

    10 ・ ・ ・ Comment ID: 1 Comment ID: 2 Comment ID: 3 Comment ID: 100 ・ ・ ・ Like ID: 1 Like ID: 2 Like ID: 3 Like ID: 100 ・ ・ ・
  5. preloadのメモリコスト 14 Article ID: 1 Article ID: 2 Article ID:

    10 ・ ・ ・ Comment ID: 1 Comment ID: 2 Comment ID: 3 Comment ID: 100 ・ ・ ・ Like ID: 1 Like ID: 2 Like ID: 3 Like ID: 100 ・ ・ ・ 約100MB
  6. preloadのメモリコスト 15 Article ID: 1 Article ID: 2 Article ID:

    10 ・ ・ ・ Comment ID: 1 Comment ID: 2 Comment ID: 3 Comment ID: 100 ・ ・ ・ Like ID: 1 Like ID: 2 Like ID: 3 Like ID: 100 ・ ・ ・ もしこれが 使われないpreloadだったら?
  7. 障害時に何が起きていたか 17 children.sizeをするためpreload Parent parent.children_countを持つ 設計の方針変更 (例: counter_cacheの導入) parent =

    Parent.preload(:children).first parent.children.each { p it.do_some } scopeの追加 (例: activeのscopeの絞り込みを追加) parent = Parent.preload(:children).first parent.children.active.each { p it. do_some } Parent Children
  8. 障害時に何が起きていたか 20 content_tag_groups.preload( content_tag: { contents: { content_publish_permission: { content_registrations:

    :available_content_selections } } } ) content_tag_groups.preload(:content_tag) 約 400 MB ↓ 80%削減
  9. まとめ 35 ⚫ 些細な負債の積み重ねが大きな障害へとつながる ⚫ 不要なpreloadという些細な問題から、プロダクトの成長によって、その 負債が蓄積し、全社的な障害へとつながった ⚫ Railsにおいても銀の弾丸は存在しない ⚫

    常にトレードオフが存在し、これを入れたら全てが解決するというような 手法は存在しない ⚫ 例えばpreloadの場合は、N+1を防げる一方で、不要なものを放置すると 多大なメモリ利用等につながる