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
73
N + 1 問題の概要と Railsにおける解決方法
toridori
January 10, 2025
Tweet
Share
More Decks by toridori
See All by toridori
Locustでmacから開発環境に負荷試験をしてみた
toridori_dev
0
79
Aurora Cloneで QA環境をつくってみた
toridori_dev
0
110
ニューモーフィズムってどうなの
toridori_dev
0
200
toridori base webをv0で爆速で作った話
toridori_dev
0
130
ハイパーパラメータチューニングって何をしているの
toridori_dev
0
230
KoT APIでプチ業務改善を試してみた
toridori_dev
0
200
MUI DataGridProコンポーネントの紹介
toridori_dev
0
420
あの日行ったマージの仕組みを僕達はまだ知らない。
toridori_dev
0
220
DBマイグレーションとORMについて
toridori_dev
0
190
Featured
See All Featured
Fireside Chat
paigeccino
34
3.2k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Facilitating Awesome Meetings
lara
51
6.2k
The Language of Interfaces
destraynor
156
24k
A designer walks into a library…
pauljervisheath
205
24k
Why You Should Never Use an ORM
jnunemaker
PRO
55
9.2k
Agile that works and the tools we love
rasmusluckow
328
21k
Six Lessons from altMBA
skipperchong
27
3.6k
How STYLIGHT went responsive
nonsquared
98
5.4k
A Philosophy of Restraint
colly
203
16k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
Side Projects
sachag
452
42k
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の発行数を抑えることができる。 まとめ
終わり