Search
Duplicate
๐Ÿš‹

์ฟผ๋ฆฌ ํŠœ๋‹ ์—ฌํ–‰

์ƒ์„ฑ์ผ
2022/10/02
ํƒœ๊ทธ
Spring
JPA
MySQL

๋ฐฐ๊ฒฝ

์ €ํฌ ํ”„๋กœ์ ํŠธ์˜ ์„œ๋น„์Šค ๋กœ์ง ๊ฐœ๋ฐœ๊ณผ ๋ฐฐํฌ๊ฐ€ ์–ด๋Š์ •๋„ ๋งˆ๋ฌด๋ฆฌ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์—ด์‹ฌํžˆ ํ…Œ์ด๋ธ”์„ ์„ค๊ณ„ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์ง€๋งŒ, ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ๊ณผ ์ธ๋ฑ์Šค์— ๋Œ€ํ•œ ์ •๋ฆฌ๋Š” ํ•˜๋‚˜๋„ ๋˜์–ด ์žˆ์ง€ ์•Š์€ ์ƒํƒœ์˜€์Šต๋‹ˆ๋‹ค. ๋ฌด์—‡๋ณด๋‹ค ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ์„ฑ๋Šฅ์ด ์ž˜ ๋‚˜์˜ค๊ณ , ์–ด๋–ค ์ฟผ๋ฆฌ๊ฐ€ ์„ฑ๋Šฅ์ด ์ž˜ ๋‚˜์˜ค์ง€ ์•Š๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์นจ ์Šคํ”„๋ฆฐํŠธ 5์˜ ์š”๊ตฌ ์‚ฌํ•ญ ์ค‘ ์ฟผ๋ฆฌ๋ฅผ ํ™•์ธํ•˜๊ณ  ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๊ธฐ๋•Œ๋ฌธ์— ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ์‹คํƒœ๋ฅผ ์กฐ์‚ฌํ•˜๊ณ  ๊ฐœ์„ ํ•˜๊ณ ์ž ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ ์ •๋ณด

๊ฐ„๋‹จํ•˜๊ฒŒ ์ €ํฌ ํ”„๋กœ์ ํŠธ ๋„๋ฉ”์ธ์˜ ERD ๊ทธ๋ฆผ์„ ๊ทธ๋ ค๋ณด์•˜์Šต๋‹ˆ๋‹ค.
์‹ค์ œ ์ปฌ๋Ÿผ์€ ๋” ๋งŽ์ง€๋งŒ ์ฟผ๋ฆฌ์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ๋งŒ ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค. ์ €ํฌ ์„œ๋น„์Šค๋Š” โ€˜๊ทธ๋ฃนโ€™ ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋‹ค๋ณด๋‹ˆ, ๋ฉค๋ฒ„์™€ ํŒ€์ด ๋Œ€๋ถ€๋ถ„์˜ ๋„๋ฉ”์ธ์— ์—ฐ๊ด€ ๊ด€๊ณ„ ์„ค์ •์ด ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํˆฌํ‘œ ๋„๋ฉ”์ธ์€ 1:N:N^2 ์˜ ํ˜•ํƒœ(ํˆฌํ‘œ:ํˆฌํ‘œ ํ•ญ๋ชฉ:ํˆฌํ‘œ ๊ฒฐ๊ณผ)๋กœ ํ…Œ์ด๋ธ”์„ ์„ค๊ณ„ํ•˜์˜€๊ณ , ์•ฝ์†์žก๊ธฐ ๋„๋ฉ”์ธ์€ 1:N ์˜ ํ˜•ํƒœ๋กœ ์„ค๊ณ„๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ •๋ณด

๊ธฐ์กด ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•˜๋˜ ๋ฐ์ดํ„ฐ ์ˆ˜๋กœ๋Š” ์ฟผ๋ฆฌ ์ƒํƒœ๊ฐ€ ์•„๋ฌด๋ฆฌ ๋‚˜๋น ๋„ ๋ˆˆ์— ์ž˜ ๋„์ง€ ์•Š๊ธฐ๋•Œ๋ฌธ์—, ์–ด๋Š์ •๋„์˜ ๋ถ€ํ•˜๋ฅผ ์œ„ํ•ด ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
โ€ข
๋ฉค๋ฒ„: 500
โ€ข
ํŒ€: 1000
โ€ข
ํŒ€ ๋ฉค๋ฒ„: 2996
โ—ฆ
1๋ฒˆ ๋ฉค๋ฒ„๋Š” ํ…Œ์ŠคํŠธ ํŽธ์˜์ƒ ๋ชจ๋“  ํŒ€์— ์ฐธ์—ฌ, ์ด์™ธ 499๋ช…์˜ ๋ฉค๋ฒ„๋Š” 4๊ฐœ์˜ ํŒ€์— ์ฐธ์—ฌ
โ€ข
ํˆฌํ‘œ: 30000
โ—ฆ
๊ฐ ํŒ€๋‹น 30๊ฐœ์˜ ํˆฌํ‘œ ์ƒ์„ฑ
โ€ข
ํˆฌํ‘œ ํ•ญ๋ชฉ: 90000
โ—ฆ
ํˆฌํ‘œ๋‹น 3๊ฐœ์˜ ํˆฌํ‘œ ํ•ญ๋ชฉ
โ€ข
ํˆฌํ‘œ ๊ฒฐ๊ณผ: 180000
โ—ฆ
ํˆฌํ‘œ ํ•ญ๋ชฉ๋‹น 2๋ช… ํˆฌํ‘œ
โ€ข
์•ฝ์†์žก๊ธฐ: 30000
โ—ฆ
๊ฐ ํŒ€๋‹น 30๊ฐœ์˜ ์•ฝ์†์žก๊ธฐ ์ƒ์„ฑ
โ€ข
์•ฝ์† ๊ฐ€๋Šฅ ์‹œ๊ฐ„: 960000
โ—ฆ
ํ•˜๋ฃจ 4์‹œ๊ฐ„, 4์ผ ์„ ํƒ
โ—ฆ
ํ•˜๋‚˜์˜ row ๊ฐ€ 30๋ถ„์ด๊ธฐ๋•Œ๋ฌธ์— 4 * 2 * 4 * 30000

๋ฉค๋ฒ„์™€ ํŒ€์ด ์ ์€ ์ด์œ 

์‹ค์ œ ์„œ๋น„์Šค๋ฅผ ๊ฐ€์ •ํ•œ ๋”๋ฏธ ๋ฐ์ดํ„ฐ์ด๊ธฐ๋•Œ๋ฌธ์— ํ•œ ํŒ€์— ์ˆ˜๋งŒ๋ช…์ด ๋“ค์–ด๊ฐ„ ์ƒํ™ฉ์€ ๊ณ ๋ คํ•˜์ง€ ์•Š๊ธฐ๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ๋ฉค๋ฒ„์™€ ํŒ€์˜ ์ˆ˜๋Š” ๋”๋ฏธ ๋ฐ์ดํ„ฐ์šฉ์œผ๋กœ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ์ˆ˜๋ฅผ ์‚ฝ์ž…ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ DB ํ™˜๊ฒฝ

spring: datasource: driver-class-name: org.h2.Driver url: jdbc:h2:~/perform;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
YAML
๋ณต์‚ฌ
ํ…Œ์ŠคํŠธ DB๋Š” h2๋กœ ๊ตฌ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์šด์˜ ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•˜๋Š” MySQL ์ด๋ฉด ๊ฐ€์žฅ ์ข‹์•˜๊ฒ ์ง€๋งŒ, ์˜ต์…˜์œผ๋กœ MODE=MySQL ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ฟผ๋ฆฌ ์ƒ์„ฑ ๋ฐฉ์‹์ด MySQL ๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š์•„ ๊ตณ์ด docker ํ™˜๊ฒฝ์„ ์„ธํŒ…ํ•˜์—ฌ ๋ฒ„์ „์„ ๋งž์ถœ ํ•„์š”์„ฑ์„ ๋Š๋ผ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐฉ์‹์€ in-memory ๋Œ€์‹  ๋””์Šคํฌ์— ์‹ค์ œ๋กœ ์“ฐ๋Š” ํ™˜๊ฒฝ์œผ๋กœ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. in-memory ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ์ด์œ ๋Š” ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
โ€ข
์‹ค์ œ ํ™˜๊ฒฝ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด
โ€ข
๋”๋ฏธ ๋ฐ์ดํ„ฐ ์‚ฝ์ž… ๋ฐฉ์‹
์•ž์„œ ์–ธ๊ธ‰ํ•œ๋Œ€๋กœ, ์šด์˜ ์„œ๋ฒ„๋Š” MySQL ์„ ์‚ฌ์šฉํ•˜๊ธฐ๋•Œ๋ฌธ์— in-memory ๋ณด๋‹ค๋Š” disk ์“ฐ๊ธฐ ๋ฐฉ์‹์ด ๋” ์ ์ ˆํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํ˜„์žฌ ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์‚ฝ์ž… ๋ฐฉ์‹์€ for ๋ฌธ์„ ๋Œ๋ฉด์„œ JPA ๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฝ์ž…ํ•˜๊ธฐ๋•Œ๋ฌธ์— in-memory ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด out of memory ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๋ฐฉ์‹

ํ…Œ์ŠคํŠธ ๋ฐฉ์‹์œผ๋กœ๋Š” ํ˜„์žฌ ์ด์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  API ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›๋Š” ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์—์„œ ๊ฐ๊ฐ API์˜ ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜, ์ฟผ๋ฆฌ ์‹œ๊ฐ„์„ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.
โ€ข
์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„
โ—ฆ
interceptor ์—์„œ๋ถ€ํ„ฐ ์ธก์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. filter ์—์„œ ์ธก์ •ํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์Šคํ”„๋ง ์ปจํ…์ŠคํŠธ๋กœ ์š”์ฒญ์ด ๋“ค์–ด์˜จ ์ดํ›„๋ถ€ํ„ฐ ์ธก์ •ํ•˜๋Š” ๊ฒƒ์ด ๋” ์ ์ ˆํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์„œ๋น„์Šค ๋กœ์ง ์ฒ˜๋ฆฌ ์ดํ›„ interceptor ์—์„œ ์‘๋‹ต ๋กœ์ง์ธ postHandle() ์—์„œ ์†Œ์š” ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•˜๊ณ  ๋กœ๊ทธ๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
โ€ข
์ฟผ๋ฆฌ ๊ฐœ์ˆ˜
โ—ฆ
PreparedStatement ์—์„œ executeQuery() ๋˜๋Š” executeUpdate() ์™€ ๊ฐ™์€ ์ฟผ๋ฆฌ ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ AOP ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋œ ๊ฐœ์ˆ˜๋ฅผ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค. ์Œ“์ธ ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜๋Š” interceptor ์—์„œ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅ๋˜๊ณ  ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.
โ€ข
์ฟผ๋ฆฌ ์‹œ๊ฐ„
โ—ฆ
์ฟผ๋ฆฌ ์‹œ๊ฐ„ ์—ญ์‹œ ์œ„์˜ ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜์™€ ๊ฐ™์ด PreparedStatement ์—์„œ ์ฟผ๋ฆฌ ๊ด€๋ จ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์ธก์ •๋ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ API ์—์„œ ๋ฐœ์ƒํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋ผ๋ฉด ๊ฐ๊ฐ์˜ ์ฟผ๋ฆฌ๋งˆ๋‹ค ์ธก์ •ํ•˜์—ฌ ๋ˆ„์ ํ•ฉ๋‹ˆ๋‹ค. ๋ˆ„์ ๋œ ์ฟผ๋ฆฌ ์‹œ๊ฐ„์€ interceptor ์—์„œ ๋กœ๊ทธ๋กœ ์ถœ๋ ฅ๋˜๊ณ  ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.
์œ„์™€ ๊ฐ™์ด ์ธก์ • ๋Œ€์ƒ์„ ์„ค์ •ํ•œ ๋’ค ํ…Œ์ŠคํŠธ๋ฅผ ๋Œ๋ ค ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
====== ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ start ====== ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ์‹œ๊ฐ„: 54.592000 ====== ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ start ====== [ํŒ€ & ๋ฉค๋ฒ„ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ] uri: '/api/groups', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 793.211833 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 3, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 25.323343 ms uri: '/api/groups/vsvRh4dC/invitation', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 173.947751 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 3, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 27.280218 ms uri: '/api/groups/in/cPUfheEe', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 79.536458 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 3, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.972297 ms uri: '/api/groups/in/cPUfheEe', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 33.633054 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 5, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 12.546666 ms uri: '/api/groups', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 6699.832034 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 1002, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 308.643746 ms uri: '/api/groups/vsvRh4dC/members', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 262.447658 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 5, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 48.182770 ms uri: '/api/groups/default', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 28.185598 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 2, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 14.102089 ms uri: '/api/groups/out/vsvRh4dC', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 113.129437 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 3, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 28.408655 ms [์•ฝ์†์žก๊ธฐ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ] uri: '/api/groups/code1/appointments', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 418.059500 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 5, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 15.378402 ms uri: '/api/groups/code1/appointments', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 1043.489309 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 3, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 932.268314 ms uri: '/api/groups/code1/appointments/K5HWZoJ0', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 24.979690 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.557007 ms uri: '/api/groups/code1/appointments/K5HWZoJ0', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 5575.911353 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 8, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 5305.979040 ms uri: '/api/groups/code1/appointments/K5HWZoJ0', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 3576.951226 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 11, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 3511.593918 ms uri: '/api/groups/code1/appointments/K5HWZoJ0', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 3804.372983 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 8, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 3720.919665 ms uri: '/api/groups/code1/appointments/K5HWZoJ0/recommendation', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 3020.213268 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 9, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 2897.717361 ms uri: '/api/groups/code1/appointments/K5HWZoJ0/close', method: 'PATCH', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 34.156669 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 4.635747 ms uri: '/api/groups/code1/appointments/K5HWZoJ0', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 2457.826639 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 38, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 2421.609196 ms [ํˆฌํ‘œ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ] uri: '/api/groups/code2/polls', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 8237.231234 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 8102.479655 ms uri: '/api/groups/code2/polls', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 297.653430 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 7, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 6.980373 ms uri: '/api/groups/code2/polls/Rvt2DhpS', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 1246.616450 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 1217.621209 ms uri: '/api/groups/code2/polls/Rvt2DhpS/items', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 49.178156 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 7, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 4.100732 ms uri: '/api/groups/code2/polls/Rvt2DhpS', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 90.324972 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 11, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 1.794396 ms uri: '/api/groups/code2/polls/Rvt2DhpS', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 913.480279 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 13, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 881.921218 ms uri: '/api/groups/code2/polls/Rvt2DhpS', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 789.068342 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 12, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 762.083852 ms uri: '/api/groups/code2/polls/Rvt2DhpS/result', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 660.966086 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 8, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 624.053410 ms uri: '/api/groups/code2/polls/Rvt2DhpS/close', method: 'PATCH', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 22.404780 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 6.660639 ms uri: '/api/groups/code2/polls/Rvt2DhpS', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 682.985367 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 14, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 641.630130 ms
YAML
๋ณต์‚ฌ
ํ•œ ๋ˆˆ์— ๋ด๋„ ๋Œ€๋ถ€๋ถ„์˜ API ์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์”ฉ ๋œฏ์–ด๋ณด๋ฉด์„œ ๊ฐœ์„ ํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ 1 - ๋ถˆํ•„์š”ํ•œ ์กฐ์ธ

uri: '/api/groups/vsvRh4dC/members', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 262.447658 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 5, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 48.182770 ms
Java
๋ณต์‚ฌ
์œ„์˜ API ๋Š” ๊ทธ๋ฃน์— ์†ํ•œ ๋ฉค๋ฒ„ ๋ชฉ๋ก ์กฐํšŒ API ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น API ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ 4๊ฐœ์˜ ๋กœ์ง์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
1.
ํŒ€ ์ฝ”๋“œ๋กœ ํŒ€ ์กฐํšŒ
2.
์š”์ฒญํ•œ ๋ฉค๋ฒ„๊ฐ€ ๊ทธ๋ฃน์— ์†ํ•ด์žˆ๋Š”์ง€ ํŒ€๋ฉค๋ฒ„ ํ™•์ธ
3.
1๋ฒˆ์—์„œ ์กฐํšŒํ•œ ํŒ€ id ๋กœ ํŒ€๋ฉค๋ฒ„ ๋ชฉ๋ก ์กฐํšŒ
4.
์กฐํšŒํ•œ ํŒ€๋ฉค๋ฒ„ ๋ชฉ๋ก์˜ for ๋ฌธ์„ ๋Œ๋ฉด์„œ Member ์กฐํšŒ
โ€ข
์ด ๋กœ์ง์œผ๋กœ ์ธํ•ด N+1 ๋ฌธ์ œ๋„ ํ•จ๊ป˜ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํŒ€๋‹น 2๋ช…์˜ ๋ฉค๋ฒ„๊ฐ€ ์žˆ๊ธฐ์— 2๊ฐœ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์•„๋ž˜์—์„œ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.
์™ผ์ชฝ์ด 2๋ฒˆ ๋กœ์ง์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•œ ์ฟผ๋ฆฌ์ด๊ณ , ์˜ค๋ฅธ์ชฝ์ด 3๋ฒˆ ๋กœ์ง์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•œ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ด์ƒํ•˜๊ฒŒ๋„ left outer join ์ด ๋‚˜ํƒ€๋‚˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. join ๋ฌธ์€ ๋น„์šฉ์ด ๋งŽ์ด ์†Œ์š”๋˜๋Š” ์ฟผ๋ฆฌ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
์™ธ๋ž˜ํ‚ค๋กœ ํ…Œ์ด๋ธ”์— ์กด์žฌํ•˜๋Š” id ๋กœ ์กฐํšŒ๋ฅผ ํ–ˆ๋Š”๋ฐ ์™œ join ๋ฌธ์ด ๋ฐœ์ƒํ•œ ๊ฒƒ์ผ๊นŒ์š”? ํ•ด๋‹น ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.
// 2๋ฒˆ ๋กœ์ง(TeamMemberRepository#existsByTeamIdAndMemberId) boolean existsByTeamIdAndMemberId(Long teamId, Long memberId); // 3๋ฒˆ ๋กœ์ง(TeamMemberRepository#findAllByTeamId) List<TeamMember> findAllByTeamId(Long teamId);
Java
๋ณต์‚ฌ
ํ•ด๋‹น ์ฟผ๋ฆฌ๋Š” ์œ„์˜ JPA ๋ฉ”์„œ๋“œ๋กœ ์ƒ์„ฑํ•œ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ DB ์ƒ์—์„œ ์ง์ ‘ ์ฐธ์กฐ๋กœ ๋งบ์–ด์ ธ์žˆ๋Š” ๊ทธ๋ฃน, ํŒ€๋ฉค๋ฒ„, ๋ฉค๋ฒ„ ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ํ‚ค๊ฐ€ ์„œ๋กœ์˜ id ๋กœ ์ €์žฅ๋˜์–ด ์žˆ์ง€๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ ๊ฐ์ฒด ์—”ํ‹ฐํ‹ฐ๋Š” ์„œ๋กœ์˜ ๊ฐ์ฒด๋กœ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผย JPQL๊ณผย SQL์„ ํ—ท๊ฐˆ๋ ค ์œ„์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.ย  TeamMemberย ๋ผ๋Š” entity๊ฐ€ ๊ฐ–๊ณ ์žˆ๋Š” ๊ฐ์ฒด๋Š”ย team_id๊ฐ€ ์•„๋‹Œย team์ด๊ณ , ๋”ฐ๋ผ์„œ team์ด ๊ฐ–๊ณ  ์žˆ๋Š” id ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์กฐํšŒํ•˜๊ณ ์ž ์œ„์™€ ๊ฐ™์€ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์กฐ๊ธˆ ๋” ์‰ฝ๊ฒŒ ์ƒ๊ฐํ•˜๋ฉด findAllByTeamName ๊ณผ ์œ ์‚ฌํ•œ ๋กœ์ง์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ฐœ์„  ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•˜๊ฒŒ, entity๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์กฐํšŒํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
// TeamMemberRepository#existsByTeamAndMember boolean existsByTeamAndMember(Team team, Member member); // TeamMemberRepository#findAllByTeam List<TeamMember> findAllByTeam(Team team);
Java
๋ณต์‚ฌ
๋ถˆํ•„์š”ํ•œ join ์ฟผ๋ฆฌ ์—†์ด ์ €ํฌ๊ฐ€ ์˜๋„ํ•œ๋Œ€๋กœ ๊ณง๋ฐ”๋กœ where ์ ˆ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ์„ ๋œ ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ์†Œ์š” ์‹œ๊ฐ„๋„ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
uri: '/api/groups/zev3uwpO/members', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 18.582039 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.983328 ms
SQL
๋ณต์‚ฌ
๊ฐœ์„  ์ „๊ณผ ํ›„ ์ฟผ๋ฆฌ ์†Œ์š” ์‹œ๊ฐ„์˜ ์ฐจ์ด๋Š” ์•ฝ 50๋ฐฐ(48ms โ†’ 0.98ms)์ธ๋ฐ์š”, ์ด๋Š” join ํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๋งŽ์•„์งˆ์ˆ˜๋ก ์ฐจ์ด๋Š” ๋” ํฌ๊ฒŒ ๋‚  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ 2 - N+1 ๋ฌธ์ œ

uri: '/api/groups', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 6699.832034 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 1002, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 308.643746 ms
Java
๋ณต์‚ฌ
์œ„์˜ API ๋Š” ์†Œ์†๋œ ๊ทธ๋ฃน ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๋Š” API ์ž…๋‹ˆ๋‹ค. ์ •ํ™•ํ•˜๊ฒŒ N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์„ ์ง์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
DBMS ํˆด์„ ์ด์šฉํ•ด ์ง์ ‘ ์ฟผ๋ฆฌ๋ฌธ์„ ๋งŒ๋“ค์–ด ์กฐํšŒํ•  ๋•Œ๋Š” N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ํž˜๋“ญ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ์ด ์ง์ ‘ ์น˜๋‹ˆ ๊ตณ์ด N+1 ๋งŒํผ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ €ํฌ ๋ชจ๋ฝ ํ”„๋กœ์ ํŠธ๋Š” JPA๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , JPA ์— ์˜ํ•ด ์ž๋™ํ™”๋œ ์ฟผ๋ฆฌ๋ฌธ๋“ค์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•„์—ฐ์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ๋ฌผ๋ก  EAGER ์˜ต์…˜ ๋˜๋Š” JdbcTemplate ์œผ๋กœ N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, JPA ์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉฐ ์–ป๋Š” ํšจ์œจ์ด ๋” ํฌ๊ธฐ๋•Œ๋ฌธ์—, ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์œ„์˜ API ์—์„œ๋Š” ์•„๋ž˜์˜ 3๊ฐ€์ง€ ๋กœ์ง์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.
1.
Member ์กฐํšŒ (1๋ฒˆ)ย 
a.
select * from member where id = ?
2.
Member๊ฐ€ ์†ํ•ด ์žˆ๋Š” TeamMember ๋ชฉ๋ก์„ ์กฐํšŒ (1๋ฒˆ)ย 
a.
select * from team_member where member_id = ?
3.
TeamMember ๋ชฉ๋ก์—์„œ ๊ฐ๊ฐ์˜ Team์„ ์กฐํšŒย 
a.
select * from team where id = ?ย * 1000
3๋ฒˆ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋ฉด์„œ ์•„์ง ํ”„๋ก์‹œ ๊ฐ์ฒด๋กœ ์žˆ๋˜ TeamMember ๊ฐ์ฒด์˜ Team ์— ๋Œ€ํ•ด for ๋ฌธ์„ ๋Œ๋ฉด์„œ ์กฐํšŒ๋ฅผ ์š”์ฒญํ•˜์—ฌ 1000๋ฒˆ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

fetch join

์ด ๋ฌธ์ œ๋Š” TeamMember ๋ฅผ ์กฐํšŒํ•  ๋•Œ team ์— ๋Œ€ํ•œ ์ •๋ณด๊นŒ์ง€ ํ”„๋กœ์ ์…˜์œผ๋กœ ๊ฐ€์ ธ์™€ JPA ์—์„œ Team ๊ฐ์ฒด์— ๋งคํ•‘ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋Š” fetch join ์œผ๋กœ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
// TeamMemberRepository#findAllByMember @Query("SELECT tm FROM TeamMember tm JOIN FETCH tm.team WHERE tm.member = :member") List<TeamMember> findAllByMember(@Param("member") Member member);
Java
๋ณต์‚ฌ
์œ„์™€ ๊ฐ™์ด JPQL ์„ ์ง์ ‘ ์ž‘์„ฑํ•˜์—ฌ fetch join ์„ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. Team ์— join ์„ ๊ฑธ๊ณ , TeamMember ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋ฉด ์กฐํšŒ ์‹œ Team ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ inner join ์œผ๋กœ ํ•จ๊ป˜ ๊ฐ€์ ธ์™€ N+1 ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@EntityGraph ๋Š”?

@EntityGraph ์„ ์‚ฌ์šฉํ•˜๋ฉด query ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ํ•ด๋‹น N+1 ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
@EntityGraph(attributePaths = {"team"}) List<TeamMember> findAllByMember(Member member);
Java
๋ณต์‚ฌ
ํ•˜์ง€๋งŒ @EntityGraph ๋กœ ๋กœ์ง์„ ๊ตฌ์„ฑํ•˜๋ฉด EAGER ๊ฐ€ ๊ธฐ๋ณธ์ด๊ธฐ๋•Œ๋ฌธ์—, ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด left outer join ์œผ๋กœ ์—ฐ๊ด€ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ @EntityGraph ๋ณด๋‹ค๋Š” inner join ์„ ์‚ฌ์šฉํ•˜๋Š” fetch join ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฒฐ์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
์–ธ์ œ๋‚˜ left outer join ์ด ๋‚˜์œ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. inner join ์€ ์—ฐ๊ด€๋œ ๊ฐ์ฒด๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์—, ์—ฐ๊ด€๋œ ๊ฐ์ฒด๊ฐ€ ์—†๋‹ค๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๊ฐ€์ ธ์˜ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด์— ๋น„์ฆˆ๋‹ˆ์Šค ์ •์ฑ…์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ 3 - ๋‹จ๊ฑด ์—…๋ฐ์ดํŠธ

uri: '/api/groups/code1/appointments/K5HWZoJ0', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 2457.826639 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 38, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 2421.609196 ms
Java
๋ณต์‚ฌ
์•ฝ์†์žก๊ธฐ ์‚ญ์ œ API ์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น API ์˜ ๋กœ์ง์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
1.
๋ฉค๋ฒ„, ๊ทธ๋ฃน ์กฐํšŒ
2.
๋ฉค๋ฒ„๊ฐ€ ๊ทธ๋ฃน์— ์†ํ•˜๋Š”์ง€ ํ™•์ธ
3.
์•ฝ์†์žก๊ธฐ ์กฐํšŒ
4.
3๋ฒˆ์˜ ์•ฝ์†์žก๊ธฐ์— ํ•ด๋‹นํ•˜๋Š” ์•ฝ์† ๊ฐ€๋Šฅ ์‹œ๊ฐ„ ์‚ญ์ œ
5.
์•ฝ์†์žก๊ธฐ ์‚ญ์ œ
4๋ฒˆ ๋กœ์ง์—์„œ๋Š” ํ•œ๋ฒˆ์— ์‚ญ์ œํ•˜๊ธฐ ์œ„ํ•ด deleteAllByAppointment ๋ฅผ ํ™œ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ 4๋ฒˆ ๋กœ์ง์—์„œ ์•ฝ์† ๊ฐ€๋Šฅ ์‹œ๊ฐ„ ์‚ญ์ œ ์‹œ, delete from ์•ฝ์†_๊ฐ€๋Šฅ_์‹œ๊ฐ„ where ์•ฝ์†์žก๊ธฐ_id=? ์ฒ˜๋Ÿผ ํ•œ ๋ฒˆ์— ์‚ญ์ œํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜์˜€๊ณ , ์˜ˆ์ƒ๋˜๋Š” ์ฟผ๋ฆฌ์˜ ๊ฐœ์ˆ˜๋Š” 6๊ฐœ์˜€์ง€๋งŒ 38๊ฐœ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์™œ์ผ๊นŒ์š”? ํ™•์ธํ•ด๋ณด๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ๋Œ๋ ค ์ฟผ๋ฆฌ๋ฅผ ํ™•์ธํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
JPA ์˜ delete ๋Š” update ์™€ ํ•จ๊ป˜ ์“ฐ๊ธฐ ์ง€์—ฐ ์ €์žฅ์†Œ์— ์ €์žฅ๋˜๋Š” ๋Œ€ํ‘œ์ ์ธ ์ฟผ๋ฆฌ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  delete ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœ๋  ๋•Œ ์‚ญ์ œํ•  ๋ฐ์ดํ„ฐ์˜ id ๋ฅผ ์ฐพ๊ธฐ์œ„ํ•ด ์ถ”๊ฐ€์ ์ธ ์กฐํšŒ ์ฟผ๋ฆฌ๊ฐ€ ํ•œ ๊ฑด ๋” ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์ฟผ๋ฆฌ๊ฐ€ ์ด์— ํ•ด๋‹นํ•˜๋Š” ์กฐํšŒ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋ฉด 1๊ฑด์ด ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ, ์™œ ์‚ญ์ œํ•  ๋ฐ์ดํ„ฐ ์ˆ˜๋งŒํผ์˜ ์ฟผ๋ฆฌ๊ฐ€ ์ถ”๊ฐ€๋กœ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.
// SimpleJpaRepository @Override @Transactional public void deleteAll(Iterable<? extends T> entities) { Assert.notNull(entities, "Entities must not be null!"); for (T entity : entities) { delete(entity); } }
Java
๋ณต์‚ฌ
์ €ํฌ ํ”„๋กœ์ ํŠธ๋Š” Repository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ , ์ƒˆ๋กญ๊ฒŒ ์ž‘์„ฑํ•œ JPA ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด SimpleJpaRepository ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ ˆํฌ์ง€ํ† ๋ฆฌ์—์„œ deleteAll ์€ ์œ„์™€ ๊ฐ™์ด ๊ตฌํ˜„๋˜์–ด ์žˆ๋Š”๋ฐ, ํ•ด๋‹น ๋ฉ”์„œ๋“œ์˜ delete ๋ฉ”์„œ๋“œ๊ฐ€ for ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ฉด์„œ ์‚ญ์ œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ์‚ญ์ œํ•  ๋ฐ์ดํ„ฐ์˜ ์ˆ˜๋งŒํผ ์ฟผ๋ฆฌ์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ถ”๊ฐ€๊ฐ€ ๋˜์—ˆ๋˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
ํ•˜๋‚˜์”ฉ ์‚ญ์ œ์ค‘,,,
์ด์— ๋”ฐ๋ผ 4๋ฒˆ ๋กœ์ง์—์„œ๋งŒ ์‚ญ์ œํ•  id ๋ฅผ ์œ„ํ•œ ์กฐํšŒ ์ฟผ๋ฆฌ 1 + ๊ฐ๊ฐ์˜ ์„ ํƒ ๊ฐ€๋Šฅ ์‹œ๊ฐ„ ์‚ญ์ œ ์ฟผ๋ฆฌ 32, ์ด 33 ๊ฑด์ด ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.
์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, deleteAllByAppointment ์—์„œ ์‚ญ์ œํ•  ์ฟผ๋ฆฌ๊ฐ€ ๊ฐ๊ฐ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ Appointment ์™€ ์ผ์น˜ํ•˜๋Š” ์•ฝ์† ๊ฐ€๋Šฅ ์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ๋ชจ๋‘๋ฅผ ์‚ญ์ œํ•˜๋Š” ์ฟผ๋ฆฌ์ธ where appointment_id=? ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

batch_size ์„ค์ •

spring: jpa: properties: hibernate: jdbc: batch_size: 1000
YAML
๋ณต์‚ฌ
์˜๋„ํ•œ ์ฟผ๋ฆฌ ๋ฐฉ์‹์ธ ๋ฒŒํฌ ์—ฐ์‚ฐ์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„ค์ • ํŒŒ์ผ์—์„œ batch_size ๋ฅผ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์˜ต์…˜์œผ๋กœ ์„ค์ •ํ•˜๋ฉด deleteAll ๊ณผ ๊ฐ™์€ ๋ฒŒํฌ ์—ฐ์‚ฐ ์ฟผ๋ฆฌ์—์„œ ํ•˜๋‚˜์˜ ์ฟผ๋ฆฌ๋งŒ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
uri: '/api/groups/code1/appointments/ZnV6dgZQ', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 23.783192 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 7, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 1.168170 ms
Java
๋ณต์‚ฌ
์‚ญ์ œํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ 1๊ฑด + ๋ฐ์ดํ„ฐ ์‚ญ์ œ ์ฟผ๋ฆฌ 1๊ฑด ์ด 2๊ฑด์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
์ฝ˜์†”์—๋Š” ์‚ญ์ œํ•  ๋ฐ์ดํ„ฐ N ๊ฑด์ด ์ฟผ๋ฆฌ๋กœ ์ฐํž™๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ connection ์œผ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ณด๋‚ด๋Š” ์ฟผ๋ฆฌ๋Š” 1๊ฐœ์ž…๋‹ˆ๋‹ค. ์“ฐ๊ธฐ ์ง€์—ฐ ์ €์žฅ์†Œ์— ์ €์žฅ ํ›„ connection ์„ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ณด๋‚ผ ๋•Œ, batch ์ฒ˜๋ฆฌํ•˜์—ฌ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
์ฃผ์˜์ ! ์‹๋ณ„์ž ์ƒ์„ฑ ๋ฐฉ์‹์ด identity ์ผ ๋•Œ๋Š” saveAll ๊ณผ ๊ฐ™์€ ์‚ฝ์ž… ๋ฒŒํฌ ์—ฐ์‚ฐ ์ฟผ๋ฆฌ์—์„œ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์‹๋ณ„์ž ์ƒ์„ฑ ๋ฐฉ์‹์€ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ insertํ•˜๊ธฐ ์ „๊นŒ์ง€ ์‹๋ณ„์ž๋ฅผ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. JPA ๋Š” ์ด์— ๋Œ€ํ•ด ์“ฐ๊ธฐ ์ง€์—ฐ ์ €์žฅ์†Œ์— ํ•ด๋‹น insert ๋ฌธ์„ ์ €์žฅํ•˜์ง€ ์•Š๊ณ , ๋ฐ”๋กœ id ๋ฅผ ํ™•์ธํ•œ ๋’ค ์ €์žฅํ•˜๊ณ  ์˜์†ํ™”์‹œํ‚ต๋‹ˆ๋‹ค. ๋งŒ์•ฝ save ์‹œ์— id ๋ฅผ ์•Œ์•„๋„, JPA ์˜ save ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋Š” merge ๋ฅผ ํ†ตํ•ด id ๊ฐ€ DB ์— ์กด์žฌํ•˜์—ฌ update ํ•˜๋Š” ์ฟผ๋ฆฌ์ธ์ง€, ์—†๋Š” id ์—ฌ์„œ insert ํ•ด์•ผํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ saveAll ์—์„œ๋Š” ํ•ด๋‹น ์„ค์ •์ด ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ง์ ‘ JPQL ์ฟผ๋ฆฌ ์ƒ์„ฑ

์กฐ๊ธˆ ๋” ์ง๊ด€์ ์ธ ๋ฐฉ์‹์€ JPQL ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.
@Modifying @Query("DELETE FROM AvailableTime at WHERE at.appointment = :appointment") void deleteAllByAppointment(@Param("appointment") Appointment appointment);
Java
๋ณต์‚ฌ
๊ธฐ์กด์— ์˜๋„ํ•œ๋Œ€๋กœ ํ•ด๋‹น ์•ฝ์†์žก๊ธฐ์— ์—ฐ๊ด€๋œ ์•ฝ์† ๊ฐ€๋Šฅ ์‹œ๊ฐ„์„ ์ฟผ๋ฆฌ ํ•˜๋‚˜๋กœ ์ƒ์„ฑํ•˜์—ฌ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๋ฐฉ์‹์€ SimpleJpaRepository ์— ๊ตฌํ˜„๋œ deleteAll ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์ง€ ์•Š๊ธฐ์— ์กฐํšŒ ์ฟผ๋ฆฌ๋„ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
uri: '/api/groups/code1/appointments/bs7yRVR3', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 16.464075 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.737359 ms
Java
๋ณต์‚ฌ
ํ•ด๋‹น ๋ฐฉ์‹์€ ์ง๊ด€์ ์ด๊ธฐ๋„ ํ•˜๊ณ , ์ฟผ๋ฆฌ ํ•˜๋‚˜๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ์ง€๋งŒ, ์“ฐ๊ธฐ ์ง€์—ฐ ์ €์žฅ์†Œ ๋‚ด์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ชจ๋‘ flush ๊ฐ€ ๋˜์–ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ด์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๋‹จ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์ €ํฌ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ํ•ด๋‹น ๋กœ์ง ์ดํ›„ ์•ฝ์† ์žก๊ธฐ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๋กœ์ง๋งŒ ์กด์žฌํ•˜๊ธฐ๋•Œ๋ฌธ์— ๋”์ด์ƒ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์ด์šฉํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ๋•Œ๋ฌธ์— ์ง์ ‘ JPQL ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๊ฐœ์„  ๊ฒฐ๊ณผ

์œ„์˜ ๊ฐœ์„ ์ ์„ ๋ชจ๋‘ ์ ์šฉํ•˜๊ณ  ๋‹ค์‹œ ํ…Œ์ŠคํŠธ๋ฅผ ๋Œ๋ ค ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
====== ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ start ====== ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ ์‹œ๊ฐ„: 50.185000 ====== ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ start ====== [ํŒ€ & ๋ฉค๋ฒ„ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ] uri: '/api/groups', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 422.165153 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 3, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 5.968536 ms uri: '/api/groups/zev3uwpO/invitation', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 82.152895 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 3.153968 ms uri: '/api/groups/in/5umvRypX', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 62.108510 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.621550 ms uri: '/api/groups/in/5umvRypX', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 24.226459 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 5, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.683008 ms uri: '/api/groups', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 3307.468467 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 2, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 30.841726 ms uri: '/api/groups/zev3uwpO/members', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 18.582039 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.983328 ms uri: '/api/groups/default', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 19.181545 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 3, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.585053 ms uri: '/api/groups/out/zev3uwpO', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 44.477059 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 2.583553 ms [์•ฝ์†์žก๊ธฐ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ] uri: '/api/groups/code1/appointments', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 303.981287 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 5, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 8.983311 ms uri: '/api/groups/code1/appointments', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 119.911311 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 10.794138 ms uri: '/api/groups/code1/appointments/dNDYqbwJ', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 18.493118 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.404567 ms uri: '/api/groups/code1/appointments/dNDYqbwJ', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 324.034765 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 8, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 58.265959 ms uri: '/api/groups/code1/appointments/dNDYqbwJ', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 53.977844 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 8, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 21.545514 ms uri: '/api/groups/code1/appointments/dNDYqbwJ', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 20.860797 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 8, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 1.450300 ms uri: '/api/groups/code1/appointments/dNDYqbwJ/recommendation', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 133.874309 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 3.223964 ms uri: '/api/groups/code1/appointments/dNDYqbwJ/close', method: 'PATCH', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 28.091637 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 4.466337 ms uri: '/api/groups/code1/appointments/dNDYqbwJ', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 35.646286 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 2.481070 ms [ํˆฌํ‘œ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ] uri: '/api/groups/code2/polls', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 149.432977 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 8.202648 ms uri: '/api/groups/code2/polls', method: 'POST', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 155.059860 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 7, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 5.191256 ms uri: '/api/groups/code2/polls/4pAWaj7K', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 19.399535 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 4, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.521628 ms uri: '/api/groups/code2/polls/4pAWaj7K/items', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 33.917882 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.785569 ms uri: '/api/groups/code2/polls/4pAWaj7K', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 70.055507 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 7, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 2.187549 ms uri: '/api/groups/code2/polls/4pAWaj7K', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 78.458004 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 9, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 11.105353 ms uri: '/api/groups/code2/polls/4pAWaj7K', method: 'PUT', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 25.122040 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 8, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 1.730743 ms uri: '/api/groups/code2/polls/4pAWaj7K/result', method: 'GET', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 20.945816 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 0.908424 ms uri: '/api/groups/code2/polls/4pAWaj7K/close', method: 'PATCH', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 43.715838 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 6, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 26.530988 ms uri: '/api/groups/code2/polls/4pAWaj7K', method: 'DELETE', ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: 26.516415 ms, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜: 13, ์ฟผ๋ฆฌ ์‹œ๊ฐ„: 1.701012 ms
YAML
๋ณต์‚ฌ
๋Œ€๋ถ€๋ถ„์˜ API ์—์„œ ์„ฑ๋Šฅ์ด ๊ฐœ์„ ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฐœ์„  ์ „/ํ›„ ๊ฐ๊ฐ ํ•ญ๋ชฉ์˜ ํ‰๊ท ์„ ๊ณ„์‚ฐํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์š”์ฒญ ์‹œ๊ฐ„
์ฟผ๋ฆฌ ๊ฐœ์ˆ˜
์ฟผ๋ฆฌ ์‹œ๊ฐ„
๊ฐœ์„  ์ „
1522.85
44.59
1166.77
๊ฐœ์„  ํ›„
208.48
5.7
7.85
์š”์ฒญ ์‹œ๊ฐ„์€ 87%, ์ฟผ๋ฆฌ ๊ฐœ์ˆ˜๋Š” 88%, ์ฟผ๋ฆฌ ์‹œ๊ฐ„์€ 148๋ฐฐ(ํผ์„ผํ…Œ์ด์ง€๊ฐ€ ๋ฌด์˜๋ฏธ) ๊ฐ€๋Ÿ‰ ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋งˆ๋ฌด๋ฆฌ

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

์ฐธ๊ณ