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
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
4 Signs Your Business is Dying
shpigford
184
22k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.3k
The Cult of Friendly URLs
andyhume
79
6.5k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.8k
Java REST API Framework Comparison - PWX 2021
mraible
31
8.6k
Writing Fast Ruby
sferik
628
61k
Stop Working from a Prison Cell
hatefulcrawdad
270
20k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
228
22k
Designing for Performance
lara
609
69k
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の発行数を抑えることができる。 まとめ
終わり