select_related, prefetch_related

2star_ยท2024๋…„ 12์›” 27์ผ
0

django

๋ชฉ๋ก ๋ณด๊ธฐ
14/18
๐Ÿ’ก **N+1 Problem**

์œ„์™€ ๊ฐ™์ด ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ง€์—ฐ๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๊ด€๋ จ๋œ ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด N๊ฐœ์˜ ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์‹คํ–‰ ๋˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๋‹น์—ฐํžˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋งŽ์€ ๋ถ€ํ•˜๊ฐ€ ๊ฑธ๋ฆฌ๊ณ  ์‘๋‹ต์‹œ๊ฐ„์ด ๋Š๋ ค์ง€๋Š” ๋“ฑ์˜ ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•ฉ๋‹ˆ๋‹ค.

  • Django์—์„œ์˜ Eager Loading
    • select_related
      • one-to-many ๋˜๋Š” one-to-one ๊ด€๊ณ„์—์„œ ์‚ฌ์šฉ
      • SQL์˜ JOIN์„ ์ด์šฉํ•ด์„œ ๊ด€๋ จ๋œ ๊ฐ์ฒด๋“ค์„ ํ•œ ๋ฒˆ์— ๋กœ๋“œํ•˜๋Š” ๋ฐฉ์‹
    • prefetch_related
      • many-to-many ๋˜๋Š” ์—ญ์ฐธ์กฐ ๊ด€๊ณ„์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉ (select_related๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ด€๊ณ„์—์„œ๋„ ๋™์ž‘)
      • ๋‚ด๋ถ€์ ์œผ๋กœ ๋‘๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋™์ž‘
        ์ฒซ๋ฒˆ์งธ ์ฟผ๋ฆฌ๋Š” ์›๋ž˜ ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๋ฉฐ ๋‘๋ฒˆ์งธ ์ฟผ๋ฆฌ๋Š” ์—ฐ๊ด€๋œ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ์‹

์ง€์—ฐ ๋กœ๋”ฉ(Lazy Loading)์€ ํ•„์š”ํ•œ ์‹œ์ ์— ๊ด€๋ จ ๊ฐ์ฒด๋ฅผ ์กฐํšŒํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์—์„œ ๋งค๋ฒˆ ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฒŒ์‹œ๊ธ€๊ณผ ์ž‘๊ฐ€ ์ •๋ณด๊ฐ€ 1๋Œ€๋‹ค(one-to-many) ๊ด€๊ณ„๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๊ณ , ๊ฒŒ์‹œ๊ธ€์„ ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ์ˆœํšŒํ•˜๋ฉด์„œ ์ž‘๊ฐ€ ์ •๋ณด์— ์ ‘๊ทผํ•œ๋‹ค๋ฉด, ๋ชจ๋“  ๊ฒŒ์‹œ๊ธ€์— ๋Œ€ํ•ด ์ž‘๊ฐ€ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๋งค๋ฒˆ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ N+1 ๋ฌธ์ œ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

N+1 ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

N+1 ๋ฌธ์ œ๋ฅผ ์ตœ์†Œํ™”ํ•˜๋ ค๋ฉด, ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ๋ฏธ๋ฆฌ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ „๋žต์ด ์ข‹์Šต๋‹ˆ๋‹ค. Django์—์„œ๋Š” select_related์™€ prefetch_related๊ฐ€ ์ด๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  1. select_related

    • ์ ์šฉ ๋Œ€์ƒ: ForeignKey๋‚˜ OneToOneField์™€ ๊ฐ™์€ 1๋Œ€1 ํ˜น์€ 1๋Œ€๋‹ค ๊ด€๊ณ„
    • ์ž‘๋™ ๋ฐฉ์‹: ๋‚ด๋ถ€์ ์œผ๋กœ SQL JOIN์„ ์‚ฌ์šฉํ•ด ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ๊ด€๋ จ ๊ฐ์ฒด๋ฅผ ๊ฐ™์ด ์กฐํšŒ
    • ํŠน์ง•: ์ง์„ ์  ๊ด€๊ณ„(์™ธ๋ž˜ ํ‚ค)๋‚˜ ์ผ๋Œ€์ผ ๊ด€๊ณ„๋Š” select_related๋กœ ๋Œ€๋ถ€๋ถ„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  2. prefetch_related

    • ์ ์šฉ ๋Œ€์ƒ: ManyToManyField ๋˜๋Š” ์—ญ์ฐธ์กฐ ๊ด€๊ณ„, ๊ทธ๋ฆฌ๊ณ  select_related๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ
    • ์ž‘๋™ ๋ฐฉ์‹: ๋‚ด๋ถ€์ ์œผ๋กœ ๋‘ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰
      • ์ฒซ ๋ฒˆ์งธ ์ฟผ๋ฆฌ: ์›๋ณธ ๊ฐ์ฒด๋“ค์„ ์กฐํšŒ
      • ๋‘ ๋ฒˆ์งธ ์ฟผ๋ฆฌ: ์—ฐ๊ด€๋œ ๊ฐ์ฒด๋“ค์„ ํ•œ๊บผ๋ฒˆ์— ๊ฐ€์ ธ์™€ ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ๊ฒฐ
    • ํŠน์ง•: select_related๊ฐ€ ์•ˆ ๋˜๋Š” ๊ด€๊ณ„์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹์œผ๋ฉฐ, ์—ฐ๊ด€๋œ ๊ฐ์ฒด๋ฅผ ํ•œ ๋ฒˆ์— ์บ์‹ฑํ•ด๋‘์–ด ์กฐํšŒ ์„ฑ๋Šฅ์„ ๋†’์ž„

์–ธ์ œ ์–ด๋Š ๋ฐฉ๋ฒ•์„ ์„ ํƒํ• ๊นŒ?

  • 1๋Œ€๋‹ค ๋˜๋Š” 1๋Œ€1 ๊ด€๊ณ„: select_related๊ฐ€ ํ›จ์”ฌ ๊ฐ„ํŽธํ•˜๊ณ  ์ฟผ๋ฆฌ ์ˆ˜๋„ ์ค„์ผ ์ˆ˜ ์žˆ์Œ
  • ๋‹ค๋Œ€๋‹ค ๋˜๋Š” ์—ญ์ฐธ์กฐ ๊ด€๊ณ„: prefetch_related๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ์œ ์šฉ

์ฃผ์˜์‚ฌํ•ญ

  • ๋ถˆํ•„์š”ํ•œ Eager Loading ์ง€์–‘
    ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์€๋ฐ๋„ ๋ฌด์กฐ๊ฑด Eager Loading์„ ์ ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊นŒ์ง€ ์กฐํšŒํ•˜๊ฒŒ ๋˜์–ด ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์–‘์ด ๋งค์šฐ ๋งŽ์„ ๋•Œ
    prefetch_related๋Š” ํ•œ ๋ฒˆ์— ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์—ฐ๊ด€ ๊ฐ์ฒด ์ˆ˜๊ฐ€ ๋งŽ์œผ๋ฉด ๋ฉ”๋ชจ๋ฆฌ์— ๋ถ€๋‹ด์ด ๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  ์ž๋ฃŒ

profile
์•ˆ๋…•ํ•˜์„ธ์š”.

0๊ฐœ์˜ ๋Œ“๊ธ€

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด