N+1 query in go
N+1, golang
N+1 Query ๋ฌธ์ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ๋ฅผ ๋นํจ์จ์ ์ผ๋ก ์ํํ๋ ํจํด์ ๋งํ๋ค.
์ฃผ๋ก ORM(Object-Relational Mapping) ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ ๋ ๋ฐ์ํ๋๋ฐ, ์ด๋ N๊ฐ์ ๋ ์ฝ๋์ ๋ํด ๊ฐ๊ฐ ์ถ๊ฐ์ ์ธ ์ฟผ๋ฆฌ๋ฅผ ์คํํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ํฉ์ ๋ปํ๋ค.
์ด ๋ฌธ์ ๋ ๋ฐ์ดํฐ ํฌ๊ธฐ์ ๋ฐ๋ผ ์ ์๋ฏธํ ์ฑ๋ฅ ์ ํ๋ฅผ ์ด๋ํ ์ ์๋ค.
N+1 Query ๋ฌธ์ ๋ฅผ ์ดํดํ๊ธฐ ์ํด ์์๋ฅผ ๋ค์ด๋ณด๊ฒ ๋ค.
๊ฐ๋ น, ๋ธ๋ก๊ทธ ํฌ์คํธ์ ๊ฐ๊ฐ์ ํฌ์คํธ์ ์ํ ๋๊ธ์ ๊ฐ์ ธ์ค๋ ์ํฉ์ ์๊ฐํด๋ณด์.
๋จผ์ , ๋ชจ๋ ๋ธ๋ก๊ทธ ํฌ์คํธ๋ฅผ ๊ฐ์ ธ์ค๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ค:
SELECT * FROM posts;๊ฐ ํฌ์คํธ์ ๋ํด ํด๋นํ๋ ๋๊ธ์ ๊ฐ์ ธ์ค๋ ์ถ๊ฐ ์ฟผ๋ฆฌ๋ฅผ 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