N+1 query in go

N+1, golang

N+1 Query ๋ฌธ์ œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๋ฅผ ๋น„ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ํŒจํ„ด์„ ๋งํ•œ๋‹ค.

์ฃผ๋กœ ORM(Object-Relational Mapping) ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์ด๋Š” N๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ์— ๋Œ€ํ•ด ๊ฐ๊ฐ ์ถ”๊ฐ€์ ์ธ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ƒํ™ฉ์„ ๋œปํ•œ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ๋ฐ์ดํ„ฐ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์œ ์˜๋ฏธํ•œ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

N+1 Query ๋ฌธ์ œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณด๊ฒ ๋‹ค.

๊ฐ€๋ น, ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ์™€ ๊ฐ๊ฐ์˜ ํฌ์ŠคํŠธ์— ์†ํ•œ ๋Œ“๊ธ€์„ ๊ฐ€์ ธ์˜ค๋Š” ์ƒํ™ฉ์„ ์ƒ๊ฐํ•ด๋ณด์ž.

  1. ๋จผ์ €, ๋ชจ๋“  ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค:

    SELECT * FROM posts;
  2. ๊ฐ ํฌ์ŠคํŠธ์— ๋Œ€ํ•ด ํ•ด๋‹นํ•˜๋Š” ๋Œ“๊ธ€์„ ๊ฐ€์ ธ์˜ค๋Š” ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๋ฅผ N๋ฒˆ ์‹คํ–‰ํ•œ๋‹ค:

    SELECT * FROM comments WHERE post_id = 1;
    SELECT * FROM comments WHERE post_id = 2;
    ...
    SELECT * FROM comments WHERE post_id = N;

์ด ๊ฒฝ์šฐ, ์ด N+1๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜๋Š”๋ฐ, ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ์— ํฐ ๋ถ€๋‹ด์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

Go์—์„œ N+1 Query ๋ฌธ์ œ ๋ฐฉ์ง€ ๋ฐฉ๋ฒ•

Go ์–ธ์–ด์—์„œ N+1 Query ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ๋กœ ORM์ด๋‚˜ SQL ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ๋Œ€ํ‘œ์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ๋Š” gorm, sqlx, ent ๋“ฑ์ด ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” gorm์„ ์‚ฌ์šฉํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค.

Eager Loading ์‚ฌ์šฉ

Eager Loading์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฐ๊ด€๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. gorm์—์„œ๋Š” Preload ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ์ฝ”๋“œ์—์„œ๋Š” Preload("Comments")๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ํฌ์ŠคํŠธ์™€ ํ•ด๋‹นํ•˜๋Š” ๋Œ“๊ธ€๋“ค์„ ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ๊ฐ€์ ธ์˜จ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด N+1 Query ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค๋งŒ Eager Loading ์€ ๋ณต์žกํ•œ ์—ฐ๊ด€ ๊ด€๊ณ„๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ ์ฟผ๋ฆฌ๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ  ์„ฑ๋Šฅ์— ์•ˆ์ข‹์€ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

Join์„ ์‚ฌ์šฉ

SQL Join์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค. ์ด๋Š” SQL ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด ์ฝ”๋“œ์—์„œ๋Š” left join์„ ์‚ฌ์šฉํ•˜์—ฌ ํฌ์ŠคํŠธ์™€ ๋Œ“๊ธ€์„ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜จ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด N+1 Query ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋Œ€์‹  ์œ„์™€ ๊ฐ™์ด Raw ์ฟผ๋ฆฌ๋กœ ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋Š” ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋‚ฎ์•„์งˆ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฟผ๋ฆฌ ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ๋‹ค.


N+1 Query ๋ฌธ์ œ๋Š” ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ํŒจํ„ด์œผ๋กœ, Eager Loading, Join, Batch Query ๋“ฑ์˜ ๊ธฐ๋ฒ•์„ ํ†ตํ•ด ์ด๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ธฐ๋ฒ•๋“ค์„ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ์˜ ํšจ์œจ์„ฑ์„ ๋†’์ด๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

Last updated