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 問題の概要と Railsにおける解決方法
Search
toridori
January 10, 2025
0
130
N + 1 問題の概要と Railsにおける解決方法
toridori
January 10, 2025
Tweet
Share
More Decks by toridori
See All by toridori
Locustでmacから開発環境に負荷試験をしてみた
toridori_dev
0
150
Aurora Cloneで QA環境をつくってみた
toridori_dev
0
200
ニューモーフィズムってどうなの
toridori_dev
0
320
toridori base webをv0で爆速で作った話
toridori_dev
0
180
ハイパーパラメータチューニングって何をしているの
toridori_dev
0
340
KoT APIでプチ業務改善を試してみた
toridori_dev
0
330
MUI DataGridProコンポーネントの紹介
toridori_dev
0
550
あの日行ったマージの仕組みを僕達はまだ知らない。
toridori_dev
0
270
DBマイグレーションとORMについて
toridori_dev
0
220
Featured
See All Featured
Automating Front-end Workflow
addyosmani
1370
200k
The Invisible Side of Design
smashingmag
299
51k
Site-Speed That Sticks
csswizardry
10
660
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
5.9k
The Cost Of JavaScript in 2023
addyosmani
51
8.4k
Measuring & Analyzing Core Web Vitals
bluesmoon
7
490
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
790
Raft: Consensus for Rubyists
vanstee
140
7k
Build The Right Thing And Hit Your Dates
maggiecrowley
36
2.8k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
124
52k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.3k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
29
9.5k
Transcript
N + 1 問題の概要と Railsにおける解決方法
田中 (25) バックエンドエンジニア1年目 駆け出していきたいです! 自己紹介
1. 今回のテーマのきっかけ 2. N + 1 問題について 3. 実際にN +
1 を体験してみる 4. Rails(ActiveRecord)を用いた検証 5. RailsにおけるN + 1 問題の解決方法 6. Rails(ActiveRecord)を用いたN+1解決後の検証 7. まとめ 目次
今回のテーマのきっかけ
今回のテーマのきっかけ 12/15 に開発部でISUCONチャレンジを行いました。
ISUCONとは 今回のテーマのきっかけ ISUCONとは、Iikanjini Speed Up Contestの略で、お題となるWebサービスを決められたレ ギュレーションの中で限界まで高速化を図るチューニングバトルです。 (引用: 高速化を図るチューニングバトル「ISUCON」とは?)
• 冗長なアプリケーションコード • N + 1 問題 • DBパフォーマンスが悪い などなど 様々な問題がありました
今回のテーマのきっかけ
N + 1 問題。 よく耳にするけど、、どういう問題 ? 今回のテーマのきっかけ
N + 1 問題について
N + 1 問題について 一覧データを取得するために SELECT を 1回 実行 表示するデータに関連するデータを取得するためのSELECTをN
回実行 データベースへのアクセスがN + 1 回実行されてしまう問題 N + 1 問題とは
文章だとイメージしづらいですね。。 N + 1 問題を経験したことある人は 心当たりがあるかも N + 1 問題について
N+1 問題について 1回の買い物でN個の商品を1個ずつ会計をしちゃうくらい無駄 N往復 どのぐらい無駄かというと、、、
実際にN + 1 を体験してみる
実際にN + 1 を体験してみる 筆者名 夏目漱石 太宰治 谷崎潤一郎 樋口一葉 森鴎外
書籍名 こころ 人間失格 細雪 たけくらべ 舞姫・沈黙の塔 筆者が複数の書籍を持つ一覧ページ N + 1 問題が起こりうる画面を作ってみる
主テーブル 従テーブル 1 : N Authors Books 1 :
N のリレーションを持つDBを用意する 実際にN + 1 を体験してみる
select * from books where author.id = n; Authors Books
select * from authors; authorsを1 回 取得すると 関連するbooksをN 回 取得してしまう。。 1 N 実際にN + 1 を体験してみる
Rails( ActiveRecord )で検証してみましょう !
Rails(ActiveRecord)を用いた検証
author 1 : N book 検証に用いるテーブル構成 Rails(ActiveRecord)を用いた検証
db/seeds.rb 筆者に書籍が複数紐づくデータを3件生成 Rails(ActiveRecord)を用いた検証
app/controllers/authors_controller.rb N + 1 問題が発生する取得処理を記述しました DBからauthorを全取得するアクションを定義 Rails(ActiveRecord)を用いた検証
関連するリソースの取得時に N + 1 問題は発生するため、 authorに紐づくbookを参照する! app/views/authors/index.html.erb point !
viewを用意する Rails(ActiveRecord)を用いた検証
authorの数だけSQLが発行されてしまっている! N + 1 問題が再現できましたね view http://localhost:3000/authors N 1
author生成数を3件にして検証! Rails(ActiveRecord)を用いた検証
正直。 3件だけじゃ問題の重大さがわかりませんね。 5 万件のレコードでN + 1 問題を発生させてみましょう ! Rails(ActiveRecord)を用いた検証
5 万件のレコードの生成 Rails(ActiveRecord)を用いた検証
N 1 viewにアクセスすると... authorレコードが 5万件あるので、 1回の authorsレコード 全取得につき、 5 万回もSQLが発行されてしまいます。。
Rails(ActiveRecord)を用いた検証 ~ 莫大なSQL発行回数 ~
N 一連の処理が終わるまでに 52156 ms 経過しています。 つまり、ページ表示に約 52 秒 かかってしまっています。。
ログを確認すると... Rails(ActiveRecord)を用いた検証 ~ ページ表示の大幅な遅延 ~
表示速度を改善したい。。。
RailsにおけるN + 1 問題の解決方法
RailsにおけるN + 1 問題の解決方法 include preload eager_load Railsでは下記 3つのメソッドで対応可能です!
authorに紐づいたbooksを一括で取得するクエリを発行してくれるので、 N回分クエリの発行が1回で収まりN + 1 問題解決 ! preload RailsにおけるN + 1
問題の解決方法
左外部結合を行い、一覧取得する 表で表すとこんなイメージ 筆者が左の場合 書籍が左の場合 eager_load RailsにおけるN + 1 問題の解決方法
左外部結合されたクエリが 実行されている ! eager_load RailsにおけるN + 1 問題の解決方法
デフォルトでは preload を使用 関連先のテーブルで絞り込みを行っている場合は eager_load と同じ挙動に include RailsにおけるN + 1
問題の解決方法
1 : N の 関連を持つデータを事前取得する場合 状況によって使い分けよう preload 関連先の要素で絞り込みを行いたい場合
eager_load 1 : 1 の関連など1クエリでデータを取得した方が効率が良い場合 include 関連先が1つだけの場合 ※ 関連が複数ある場合、個別に最適化できないので非推奨 RailsにおけるN + 1 問題の解決方法
Rails(ActiveRecord)を用いたN+1解決後の検証
preloadを用いて50000件のauthor表示の速度改善してみる Rails(ActiveRecord)を用いたN+1解決後の検証
preloadを用いて速度改善してみる author_id をひとまとめにしてbooksを取得することで、 SQL発行数が2件に! 長いので省略 Rails(ActiveRecord)を用いたN+1解決後の検証
改善後の表示速度を見ると、14015ms 経過していることがわかります。 つまり、ページ表示に約 14 秒 かかっています。 ログを確認すると... 改善前は 約
52 秒 だったので - 38秒 の改善がみられました! Rails(ActiveRecord)を用いたN+1解決後の検証
やったね !
まとめ
• ORMを利用して実装する時に、関連するリソースの取得時にN + 1 問題が発 生する場合がある。 • パフォーマンスの悪化や、過剰なSQLの発行に気づいて初めてN + 1
問題に 認知できることが多い。 • 解決策として、クエリ結合や、クエリの最適化を行うことなどがある。 それらを行うことにより、SQLの発行数を抑えることができる。 まとめ
終わり