Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
N+1と待ち時間にサヨナラ -- load_ async × strict _ loading...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yasuhiro Sugawara
August 21, 2025
21
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
N+1と待ち時間にサヨナラ -- load_ async × strict _ loading でRailsを速くする--
Yasuhiro Sugawara
August 21, 2025
More Decks by Yasuhiro Sugawara
See All by Yasuhiro Sugawara
「Hono遍歴」と「HonoXでブログ作成」
yasu551
0
630
Featured
See All Featured
BBQ
matthewcrist
89
10k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Six Lessons from altMBA
skipperchong
29
4.4k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
Evolving SEO for Evolving Search Engines
ryanjones
0
250
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
450
Practical Orchestrator
shlominoach
191
12k
Automating Front-end Workflow
addyosmani
1370
210k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
My Coaching Mixtape
mlcsv
0
190
RailsConf 2023
tenderlove
30
1.5k
Transcript
N+1と待ち時間にサヨナラ load_async × strict_loading でRailsを速くする 1
自己紹介 名前: 菅原康滉 X: @yasu551_ 仕事: ソニックガーデン Rails 趣味: 登山、読書(漫画、SF小説(プロジェクト・ヘイル・メアリー))
2
N+1と待ち時間にサヨナラ load_async × strict_loading でRailsを速くする 3
遅い画面の正体 ダッシュボードのレスポンス 1.6秒 並列化できるクエリが 直列で2本 実行 テンプレートで N+1 発生 攻めるべきは
並列化 と N+1封じ 4
並列化できるクエリが 直列で2本 実行 # app/controllers/dashboards_controller.rb def show @posts = Post.published
# SQLは未実行 @authors = Author.where(featured: true) # SQLは未実行 end <!-- app/views/dashboards/show.html.erb --> <!-- @postsのSQLが遅延実行 --> <% @posts.each do |post|> <%= post.content %> <% end %> <!-- 上の処理が終わった後に、@authorsのSQLが遅延実行 --> <!-- 上の処理が終わる前に、@authorsのSQLを実行すれば処理全体にかかる時間を削減可能 --> <% @authors.each do |author|> <%= author.name %> <% end %> 5
load_async でクエリを非同期実行して、並列化 # app/controllers/dashboards_controller.rb def show @posts = Post.published.load_async #
SQLが非同期実行 @authors = Author.where(featured: true).load_async # SQLが非同期実行 # 結果的に、@postsと@authorsの両方のSQLが並列化 end <!-- app/views/dashboards/show.html.erb --> <!-- SQL結果が未取得なら待機し、取得済みなら以下を実行 --> <% @posts.each do |post|> <%= post.content %> <% end %> <!-- SQL結果が未取得なら待機し、取得済みなら以下を実行 --> <% @authors.each do |author|> <%= author.name %> <% end %> 6
設定とログ確認 config.active_record.async_query_executor = :global_thread_pool # or multi_thread_pool tail -f log/development.log
| grep ASYNC ASYNC タグが出れば非同期実行 7
strict_loading でN+1を検出して止める class Article < ActiveRecord has_one :author end #
irb articles = Article.all.strict_loading articles.map { it.name } => ActiveRecord::StrictLoadingViolationError articles = Article.all.includes(:author).strict_loading articles.map { it.name } => ['Alice', 'Bob'] 注意: includes なしで多発 / 全体ONは段階的に 8
適用モードの段階拡大 1. 局所オン Article.all.strict_loading 2. モデル単位 class Article < ActiveRecord
self.strict_loading_by_default = true end 3. 全体適用 config.active_record.strict_loading_by_default = true config.active_record.action_on_strict_loading_violation = :log 9
効果の定量化 p95応答時間: ある期間に来た全リクエストのうち、95%がそれ以下で返っている 応答時間 p95応答時間が850msだったら、95%のリクエストは850ms以内に完了。遅 い5%だけが850ms超 DB待ち(p95): アプリのスレッドがActiveRecordの接続プールからコネクションを 取得できるまで待った時間 DB待ち(p95)が120msだったら、コネクション取得の95%が120ms以内に完
了。遅い5%だけ120ms超 N+1検出数/分: 1分あたりにN+1が起きた回数 load_async の効果は、p95応答時間、DB待ち(p95)を見ればわかる strict_loading の効果は、N+1検出数/分でわかる 10
まとめ 重い画面に load_async N+1多発領域に strict_loading 小さく入れて → ログ確認 → 段階拡大
コードを少し変えるだけで済むので簡単に試せていい 11