๋ฐฐ๊ฒฝ
์ ํฌ ํ๋ก์ ํธ์ ์๋น์ค ๋ก์ง ๊ฐ๋ฐ๊ณผ ๋ฐฐํฌ๊ฐ ์ด๋์ ๋ ๋ง๋ฌด๋ฆฌ ๋์์ต๋๋ค. ์ด์ฌํ ํ
์ด๋ธ์ ์ค๊ณํ๊ณ ์ฝ๋๋ฅผ ์์ฑํ์ง๋ง, ์ฟผ๋ฆฌ์ ์ฑ๋ฅ๊ณผ ์ธ๋ฑ์ค์ ๋ํ ์ ๋ฆฌ๋ ํ๋๋ ๋์ด ์์ง ์์ ์ํ์์ต๋๋ค. ๋ฌด์๋ณด๋ค ์ด๋ค ์ฟผ๋ฆฌ๊ฐ ์ฑ๋ฅ์ด ์ ๋์ค๊ณ , ์ด๋ค ์ฟผ๋ฆฌ๊ฐ ์ฑ๋ฅ์ด ์ ๋์ค์ง ์๋์ง์ ๋ํ ์ ๋ณด๊ฐ ์์์ต๋๋ค. ๋ง์นจ ์คํ๋ฆฐํธ 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 ๋ฑ์ ์ด์ฉํ์ฌ ๋ถํ์ํ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ ์ฟผ๋ฆฌ ์ฑ๋ฅ์ ๊ฐ์ ํด ๋ณด์์ต๋๋ค. ์ฌ์ค ๊ฐ์ ์์น๋ ํ
์คํธ ํ๊ฒฝ, ๋๋ฏธ๋ฐ์ดํฐ ์, ๊ฐ์ ์ ๋ก์ง ์ํ ๋ฑ ๋ง์ ๋ถ๋ถ์์ ์ํฅ์ ๋ฐ์ ์ ์์ด ํฌ๊ฒ ์ ์๋ฏธํ๋ค๊ณ ์๊ฐํ์ง๋ ์์ต๋๋ค. ์ด๋ฌํ ๊ฐ์ ์ ์์ ์ค์ํ ๊ฒ์ ์ด๋ค ๋ถ๋ถ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋์ง, ์ด๋ป๊ฒ ๋ฌธ์ ์ํฉ์ ์ธ์งํ๊ณ ๋ค์ ๋ง๋ค์ด๋ผ ์ ์๋์ง, ์ด๋ค ํด๊ฒฐ ๋ฐฉ๋ฒ๋ค์ด ์๊ณ ์๋น์ค ์ ์ฑ
์ ๋ง๋ ์ต์ ์ ํด๊ฒฐ์ฑ
์ ์ ์ฉํ ์ ์๋์ง๋ผ๊ณ ์๊ฐํฉ๋๋ค.