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問題について調べてみた
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yuxki
July 01, 2024
23
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
N+1問題について調べてみた
N+1問題について調べてみた
Yuxki
July 01, 2024
More Decks by Yuxki
See All by Yuxki
TypeScriptのクロージャで型エ ラーにハマった話
yuxki
0
26
Conoha VPSでIaCはできる!!!
yuxki
0
220
個人ブログ作ってデプロイしました。
yuxki
0
58
チームでプロダクトを作る機会でタスクの自走に役立った、個人開発の経験や習慣。
yuxki
0
58
Featured
See All Featured
Everyday Curiosity
cassininazir
0
280
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
Designing for humans not robots
tammielis
254
26k
The Curious Case for Waylosing
cassininazir
1
450
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Skip the Path - Find Your Career Trail
mkilby
1
180
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
560
Writing Fast Ruby
sferik
630
63k
Transcript
N+1問題について調べてみた Yukihiro Uejo 1
自己紹介 • 自己紹介 ◦ エンジニア職への就職(アプリのバックエンド)を目指して、日々勉強中です。 経験者と初心者の中間くらいだと思ってます。(実務2年 →個人開発3年) ▪ 実務2年では、主にJavaとSQLで管理会計のWEBアプリを開発 ▪
個人開発では、主にセキュリティと VPSでオンプレっぽくインフラを勉強して いました。 ◦ Vimmer ◦ Go,Python,TypeScript ◦ 委託開発先ではバックエンドの開発をやってます。 ▪ 約半年生き残りました!🎉🎉🎉 2
「N+1問題」について調べようと思ったきっかけ • ORMで、N(N(N+1)+1)+1みたいなことをしているのを見かけて、クエリが 爆発的に増加していたところに出くわしたから。 • 以前の発表でもN+1というワードが出てきて、「?」となったので、調べて みることにした。 3
「N+1問題」の概要 N + 1 1回SELECT句を実行して返されるN行のレコード 関連情報を取得するために、N回SELECT句を実行。 4 のパフォーマンスが悪くなったときに生じる問題。
問題の部分はさておいて、 「N+1」の現象を例から追ってみる 5
「N+1」の例 (テーブル) 6 author(著者) ID id 名前 name 生年月日 birthday
book(本) ID id 名前 name 著者ID author_id 言語ID language_id • 本テーブルが著者テーブルと言語テーブルとのリレーションを持つとする。 language(言語) ID id 名前 name
「N+1」の例 (レコード) 7 • 以下のようなレコードを持つとする book(本) id name author_id language_id
1 Javaの基礎 1 1 2 Goの基礎 1 1 language(言語) id name 1 日本語 author(著者) ID name birthday 1 山田太郎 1991/01/01
「N+1」の例 (求める結果) 8 • 本のIDをリクエストパラメータとして渡すと、以下のような結果をAPIから 返してほしい。 { “id”: “1”, “name”:
“Javaの基礎”, “author”: “山田太郎”, “言語”: “日本語” }
「N+1」の例 (処理) 9 • 以下のような処理を実行する。(ピンク色はレスポンスするパラメータ) 1. SELECT * FROM book
WHERE book.id = “1”;を実行する 2. {“id”: “1”, “name”:“Javaの基礎”, “author_id”: “1”, “language_id”: “1”}が返る。これを元にさらにSELECT句を実行する。 3. SELECT * FROM author WHERE author.id = 1;を実行する。 4. {“id”: “1”, “name”:“山田太郎”}が返る 5. SELECT * FROM language WHERE language.id = 1;を実行する。 6. {“id”: “1”, “name”:“日本語”}が返る このネスト構造のような取得方法が「N+1」という現象。
別にコレ自体が悪いわけではない。 では問題は? 10
問題としての「N+1」 11 テーブルA テーブルB テーブルC • 以下のようなデータ構造があったとして、A~Fのデータが必要で、「N+1」の方法で 取得するとする。すると最低でも合計5クエリ必要。 • 中間テーブルのレコード数が1つ増えるたびに、3テーブル分のクエリが追加され
る。 • このデータ構造からリスト形式の画面を作るとなると、テーブル B以降のクエリの多 さはテーブルAから読み取るレコードに比例して多くなる。 中間テーブルZ テーブルG テーブルH
こういった感じでクエリの数が爆発てきに増え、DBの 性能との兼ね合いで、ユーザーに不便が生じる程の パフォーマンスになる可能性がある。 12
では解決方法は? 13 • ORMによって具体的な解決方法は異なるらしいが、Djangoでは各テーブルを 結合してSELECTするための関数を使うことで、クエリの数を減らす対応が 考えられる。 • また、どのORMにも共通して言えることは素のSQLを書いてしまうことであ る。
まとめ • N+1とは、入れ子構造になったSELECT句の実行形式である。 • N+1となる事自体が問題ではなく、業務上悪いパフォーマンスになること が、N+1問題。 • 解決方法としてシンプルなのは、結合を用いたSQLをORMに書かせること、 または自分でSQLを書くこと。 14
参考文献 • Railsライブラリ紹介 : N+1問題を検出する「 bullet」 ◦ https://www.techscore.com/blog/2012/12/25/rails%E3%83%A9%E3%82%A4%E3% 83%96%E3%83%A9%E3%83%AA%E7%B4%B9%E4%BB%8B-n1%E5%95%8F%E9%A1%8C%E3%82% 92%E6%A4%9C%E5%87%BA%E3%81%99%E3%82%8B%E3%80%8Cbullet%E3%80%8D/
15