๐คจ N+1 ๋ฌธ์ ๋?
๐ ๋ญ๋ฐ?
๊ฐ๋จํ ๋งํด์ ๋ง์ SQL ์ฟผ๋ฆฌ๊ฐ ๋ฃจํ์์ ์คํ๋ฉ๋๋ค.
๐ ์๋ฅผ ๋ค์ด
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ ๊ฐ์ ํ ์ด๋ธ์ด ์์ต๋๋ค.
โผ ์ปจํธ๋ฆฌ ํ ์ด๋ธ
ID
์ด๋ฆ
1
์ผ๋ณธ
2
ํด๋๋
โผ ์ํ
ID
country_id
์ด๋ฆ
1
1
ํ
2
1
๋ผ๋ฉด
์ผ
1
์ฐ๋
4
2
ํผ์๋ก๊ธฐ
5
2
์ฝํ๋
6
2
์ง๋์ํค
๊ตญ๊ฐ ์ด๋ฆ ์ป๊ธฐ
(๋ฃจ๋น ์ฝ๋๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค)
# SELECT * FROM country;
Country.all.each do |country|
put country.name
# Japan
# Poland
end
๋ฃจํ์์ ๋ค๋ฅธ ํ ์ด๋ธ ํธ์ถ
# SELECT * FROM country;
Country.all.each do |country|
put country.name
# Japan
# Poland
# SELECT * FROM food WHERE country_id=1;
# SELECT * FROM food WHERE country_id=2;
# ๐ซ ๐ญ if country table had 200 records, 200 query would be executed!!! OMG
country.foods.each do |food|
put food.name
# sushi
# ramen
# udon
# pierogi
# kotlet
# ziemniaki
end
end
๐ ํด๊ฒฐ ๋ฐฉ๋ฒ์?
๊ฐ์ ํ๋ค
ํ ์ด๋ธ ํตํฉ!
# SELECT * FROM country INNER JOIN food ON country.id=food.country_id
# ๐ ๐ only 1 query !
Country.join(:food).all.each do |country|
country.foods.each do |food|
end
end
์ฆ์ ๋ก๋
JOIN์ฒ๋ผ ์์ ํ ํ ์ด๋ธ์ ํตํฉํ๋ ๊ฒ์ด ์๋๋ผ ์ฒ์์ SELECT๋ฅผ ์คํํฉ๋๋ค!
# SELECT * FROM country;
# SELECT * FROM food WHERE country_id IN(1,2)
# ๐ ๐ only 2 queries !
Country.includes(:food).all.each do |country|
country.foods.each do |food|
end
end
โญ Ruby์์ ์ฆ์ ๋ก๋๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํฌํจ์ ์ฌ์ฉํ์ญ์์ค.
๐ ๋จ์
Join/Eager ๋ก๋๊ฐ ์ฒ์์ ๊ฑฐ๋ํ SELECT๋ฅผ ์คํํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ๋์
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐คจ N+1 ๋ฌธ์ ๋?), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/kaziusan/what-is-n1-problem-2h1aํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค