๐Ÿคจ N+1 ๋ฌธ์ œ๋ž€?

4494 ๋‹จ์–ด beginnersdatabasemysqlsql

๐Ÿ’Ž ๋ญ”๋ฐ?



๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ ๋งŽ์€ 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๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜

    ์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ