Search
Duplicate
๐ŸŽณ

์ธ๋ฑ์Šค ์ตœ๋Œ€ ํ™œ์šฉํ•˜๊ธฐ (where + group by + order by)

์ƒ์„ฑ์ผ
2023/01/22
ํƒœ๊ทธ
MySQL
Spring
๋ชฉ์ฐจ

๋ฐฐ๊ฒฝ

์ €ํฌ ๋ชจ๋ฝ์—์„œ๋Š” ์—ญํ•  ์ •ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ค‘ ์—ญํ•  ๊ธฐ๋ก ์กฐํšŒ API ์—์„œ ์žˆ๋˜ ํ•œ๋ฐฉ ์ฟผ๋ฆฌ๋Š” ์„œ๋ธŒ ์ฟผ๋ฆฌ๊ฐ€ 2๊ฐœ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์„ฑ๋Šฅ์ƒ ๋น„ํšจ์œจ์ ์ด์—ˆ๊ณ , ์ด๋ฅผ 4๊ฐœ์˜ ์ฟผ๋ฆฌ๋กœ ๋‚˜๋ˆ„์–ด ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด 4๊ฐœ์˜ ์ฟผ๋ฆฌ ์ค‘ ๋‹ค๋ฅธ ์ฟผ๋ฆฌ๋“ค์— ๋น„ํ•ด ์œ ๋‚œํžˆ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ฟผ๋ฆฌ๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ์š”, ๋ฐ”๋กœ ์กฐ๊ฑด์ ˆ, ๊ทธ๋ฃนํ™”, ์ •๋ ฌ์ด ๋ชจ๋‘ ๋“ค์–ด๊ฐ„ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์กด์žฌํ•˜๋Š” ํด๋Ÿฌ์Šคํ„ฐ๋ง ์ธ๋ฑ์Šค์™€ ์™ธ๋ž˜ํ‚ค ์ธ๋ฑ์Šค๋กœ๋Š” ํ•ด๋‹น ์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ฑ์Šค๋ฅผ ํƒ€์ง€ ์•Š์•„ ๋‹ค๋ฅธ ๊ธฐ๋ณธ ์กฐํšŒ ์ฟผ๋ฆฌ์— ๋น„ํ•ด ์•ฝ 60๋ฐฐ์ •๋„ ์†Œ์š” ์‹œ๊ฐ„์ด ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ํ•ด๋‹น ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ์„ ์ตœ๋Œ€ํ•œ ๋Œ์–ด์˜ฌ๋ ค๋ณด๊ณ ์ž ์ตœ์ ์˜ ์ธ๋ฑ์Šค๋ฅผ ์ฐพ์•„๋ณด๊ธฐ๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

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

โ€ข
ํ…Œ์ŠคํŠธ DB ํ™˜๊ฒฝ
โ—ฆ
ํ…Œ์ŠคํŠธ DB ํ™˜๊ฒฝ์œผ๋กœ๋Š” ๋กœ์ปฌย docker์—ย mysql์„ ๋„์›Œ, ํ”„๋กœ์ ํŠธ์™€ ๋™์ผํ•˜๊ฒŒ DB๋ฅผ ์„ค์ •ํ•ด ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. MySQL ์€ 8 ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.
โ€ข
DB erd
โ—ฆ
์กฐํšŒํ•  ํ…Œ์ด๋ธ”์ธ role_history ์— role ํ…Œ์ด๋ธ”์˜ PK ๊ฐ€ ์™ธ๋ž˜ํ‚ค๋กœ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
โ€ข
๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ •๋ณด
โ—ฆ
role: 100
โ—ฆ
role_history: 50000 * 100
โ–ช
ํ•˜๋‚˜์˜ role ๋‹น role_history ๋ฅผ 50000 ๊ฑด์”ฉ ์‚ฝ์ž…ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
โ–ช
role ์˜ ๊ฐ role_history ๋งˆ๋‹ค ์ƒ์„ฑ ์‹œ๊ฐ„ ์ฐจ์ด๋Š” 1๋ถ„์œผ๋กœ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ์ 

ํ˜„์žฌ ๋‹ค๋ฃจ๋Š” ์—ญํ•  ๊ธฐ๋ก ์กฐํšŒ ๋Š” ๋งค๋ฒˆ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ์—ญํ• ๋“ค์„ ์ผ๋ณ„ ๊ฐ€์žฅ ๋Šฆ๊ฒŒ ๊ฐฑ์‹ ํ•œ ์—ญํ• ์„ ์กฐํšŒํ•˜๋Š” API ์ž…๋‹ˆ๋‹ค.
์œ„ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ํ•˜๋ฃจ์— 100 ๋ฒˆ์˜ ์—ญํ•  ๊ฐฑ์‹ ์„ ํ•œ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„, ๊ทธ ๋‚  ๊ฐ€์žฅ ๋Šฆ๊ฒŒ ๊ฐฑ์‹ ํ•œ ์—ญํ• ์ด ํ•ด๋‹น ๋‚ ์งœ์˜ ์—ญํ• ๋กœ ์กฐํšŒ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ API ์—์„œ ์—ญํ• ์„ ์กฐํšŒํ•˜๊ณ , ๊ทธ๋ฃนํ™”์™€ ์ •๋ ฌํ•˜๋Š” ์กฐํšŒ๋ฅผ ํ•œ ๋’ค, ์ตœ์ข…์ ์œผ๋กœ ์กฐํšŒ๋œ ์—ญํ•  ํžˆ์Šคํ† ๋ฆฌ์— ํ•ด๋‹นํ•˜๋Š” ์—ญํ•  ๊ฒฐ๊ณผ๋ฅผ ์กฐํšŒ๋ฅผ ํ•˜๋Š”๋ฐ, ๋ฌธ์ œ๊ฐ€ ๋œ ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
select max(rolehistor0_.id) as col_0_0_ from role_history rolehistor0_ where rolehistor0_.role_id=17 group by date(rolehistor0_.date_time) order by date(rolehistor0_.date_time) desc;
SQL
๋ณต์‚ฌ
์œ„์˜ ์ฟผ๋ฆฌ๋Š” where + group by + order by desc ๊ฐ€ ์„ž์—ฌ ์ฟผ๋ฆฌ์˜ ๊ธธ์ด์— ๋น„ํ•ด ๋‹ค์†Œ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ๋ณด๋ฉด ์™ธ๋ž˜ํ‚ค๋กœ ์žˆ๋Š” role_id ๋กœ ์กฐ๊ฑด์ ˆ ํ•„ํ„ฐ๋ง์„ ํ•˜๋ฉฐ, date_time์„ date ๋กœ ๋ณ€ํ˜•ํ•˜์—ฌ ๊ทธ๋ฃนํ™”๋ฅผ ํ•œ ๋’ค date_time ์—ญ์ˆœ ์ฆ‰ ์ตœ์‹  ๋‚ ์งœ ์ˆœ์œผ๋กœ ์ •๋ ฌ์„ ํ•˜๊ณ , ๊ทธ๋ฃนํ™”๋œ date_time ์—์„œ ๊ฐ€์žฅ id ๊ฐ€ ํฐ ๋ฐ์ดํ„ฐ(๋‚ ์งœ ๋ณ„ ๊ฐ€์žฅ ๋Šฆ๊ฒŒ ๊ฐฑ์‹ ํ•œ ์—ญํ• ) ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
์œ„ ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ์†๋„๋Š” ๋”๋ฏธ ๋ฐ์ดํ„ฐ ์•ฝ 500๋งŒ๊ฑด์„ ๊ธฐ์ค€์œผ๋กœ ์•ฝ 0.64์ดˆ๊ฐ€ ์†Œ์š”๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ธŒ์ฟผ๋ฆฌ๊ฐ€ ์„ž์ธ ํ•œ๋ฐฉ ์ฟผ๋ฆฌ๋ณด๋‹ค๋Š” ์„ฑ๋Šฅ์ƒ ํ›จ์”ฌ ์ข‹์•˜์ง€๋งŒ, ์‘๋‹ต๋œ ๋ ˆ์ฝ”๋“œ ์ˆ˜์— ๋น„ํ•ด์„œ๋Š” ๋‹ค์†Œ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๊ฒƒ์ด ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค.
์ฟผ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง์„ ํ†ตํ•ด ํ•ด๋‹น ์ฟผ๋ฆฌ๊ฐ€ ์–ด๋–ค ์ƒํƒœ์ธ์ง€ ํ™•์ธํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์ด ๋ฐœ์ƒํ•˜๋Š” ๋นˆ๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” context_voluntary ์™€ context_involuntary ์ปฌ๋Ÿผ์—์„œ ๊ฐ๊ฐ ์•ฝ 100 ๊ฑด๊ณผ 200 ๊ฑด์ด ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด ๋˜ํ•œ ์ด์ „ ํ•œ๋ฐฉ ์ฟผ๋ฆฌ์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ์ˆ˜์ธ ์•ฝ 10000๊ฑด์— ๋น„ํ•ด์„œ๋Š” 1% ์ˆ˜์ค€์ด์ง€๋งŒ, 35๊ฑด ๋ฐ์ดํ„ฐ ์‘๋‹ต ์ˆ˜์— ๋น„ํ•ด์„œ๋Š” ๋งŽ์€ ํŽธ์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ถ„์„ ๊ฒฐ๊ณผ๋กœ๋Š” CPU ์ž…์ถœ๋ ฅ์ด ๋งŽ์ด ๋ฐœ์ƒํ•˜์—ฌ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ์†Œ์š”๋˜์—ˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” InnoDB ์—์„œ CPU ์ž…์ถœ๋ ฅ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๋ณดํŽธ์ ์ธ ๋ฐฉ์‹์€ ์ž์ฃผ ์กฐํšŒ๋˜๋Š” ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ์ ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ํ˜„์žฌ ์ ์šฉ๋œ ์ธ๋ฑ์Šค๋ฅผ ํ™•์ธํ•ด๋ณด๊ณ , ์–ด๋–ค ํ˜•ํƒœ๋กœ ์ธ๋ฑ์Šค๋ฅผ ์ €์žฅํ•ด์•ผ ๊ฐ€์žฅ ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

index ์กฐ์‚ฌ

ํ˜„์žฌ ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” ์ธ๋ฑ์Šค๋Š” ์œ„์˜ 3๊ฐœ์ž…๋‹ˆ๋‹ค. PRIMARY ์™€ role_id ๋Š” ํ…Œ์ด๋ธ”์ด ์ƒ์„ฑ๋  ๋•Œ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ์ธ๋ฑ์Šค์ž…๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ”์ด ์ƒ์„ฑ๋  ๋•Œ, Inno DB ๋Š” ๊ธฐ๋ณธํ‚ค์™€ ์™ธ๋ž˜ํ‚ค์— ๋Œ€ํ•ด ์ž๋™์œผ๋กœ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ date_time ํ•ญ๋ชฉ์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜๊ธฐ๋•Œ๋ฌธ์— date_time ์— ๋Œ€ํ•ด์„œ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹คํ–‰ ๊ณ„ํš์„ ์‚ดํŽด๋ณด๋ฉด!
key ์ปฌ๋Ÿผ์— role_id_index ๋งŒ ์žˆ์–ด, ๊ทธ๋ฃนํ™”๋Š” ์ธ๋ฑ์Šค๋ฅผ ํƒ€์ง€ ์•Š์€ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋ฅผ ํƒ€์ง€ ์•Š์€ ์ด์œ ๋Š”, where ์ ˆ ๋˜๋Š” group by ์— ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ๋™์ผํ•œ ์ปฌ๋Ÿผ์ด ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ˜„์žฌ ์ ์šฉ๋˜์–ด ์žˆ๋Š” ์ธ๋ฑ์Šค๋Š” ์กฐ๊ฑด์ ˆ๊ณผ ๊ทธ๋ฃนํ™”์— ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ์ด ๋‹ค๋ฅด๊ธฐ๋•Œ๋ฌธ์— ๊ทธ ์ค‘ ํ•˜๋‚˜๋งŒ ์ธ๋ฑ์Šค๊ฐ€ ์ ์šฉ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ณตํ•ฉ ์ธ๋ฑ์Šค ์ ์šฉ

์ด์— ๋”ฐ๋ผ ์กฐ๊ฑด์ ˆ๊ณผ ๊ทธ๋ฃนํ™”๊ฐ€ ๋ชจ๋‘ ์ธ๋ฑ์Šค์— ์ ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ์ปฌ๋Ÿผ ์ˆœ์„œ(role_id, datetime)์— ๋งž์ถ”์–ด ๋ณตํ•ฉ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
create index role_history_index_role_id_date_time on role_history (role_id, date_time);
SQL
๋ณต์‚ฌ
๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰ ๊ณ„ํš์„ ํ™•์ธํ•ด๋ณด๋ฉด!
key ์ปฌ๋Ÿผ์— ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ (role id, date time) ์˜ ๋ณตํ•ฉ ์ธ๋ฑ์Šค๊ฐ€ ์ธ๋ฑ์Šค๋กœ ์‚ฌ์šฉ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Extra ์ปฌ๋Ÿผ์— ์ถ”๊ฐ€์ ์œผ๋กœ Using index ๊ฐ€ ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Extra ์ปฌ๋Ÿผ์˜ Using index ๋Š” ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค๊ฐ€ ์ ์šฉ๋˜์—ˆ๋‹ค๋Š” ํ‘œ๊ธฐ์ž…๋‹ˆ๋‹ค.
์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค๋Š” ์กฐํšŒํ•  ์ปฌ๋Ÿผ, ์กฐ๊ฑด์ ˆ, ๊ทธ๋ฃนํ™”, ์ •๋ ฌ ๋“ฑ์— ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ์ด ์ˆœ์„œ์— ๋งž๊ฒŒ ๋ชจ๋‘ ์ธ๋ฑ์Šค์— ํฌํ•จ๋œ ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋‘ ์ธ๋ฑ์Šค๋กœ ์ €์žฅ๋˜์–ด ์žˆ๊ธฐ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ์— ์ง์ ‘ ์ ‘๊ทผํ•  ํ•„์š”๊ฐ€ ์—†์–ด ์ฟผ๋ฆฌ์˜ ํšจ์œจ์ด ๋งค์šฐ ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ํ˜„์žฌ ๋ณตํ•ฉ ์ธ๋ฑ์Šค์— ์„ค์ •๋œ ์ปฌ๋Ÿผ์€ โ€˜role_idโ€™ ์™€ โ€˜date_timeโ€™ ์ด๊ณ , ์กฐํšŒํ•˜๋Š” ์ปฌ๋Ÿผ์€ โ€˜idโ€™ ์—ฌ์„œ ์ ์šฉ๋œ ๋ณตํ•ฉ ์ธ๋ฑ์Šค์—๋Š” id ๊ฐ€ ์—†๋Š”๋ฐ, ์–ด๋–ป๊ฒŒ ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ์ ์šฉ์ด ๊ฐ€๋Šฅํ–ˆ์„๊นŒ์š”?
์ด๋Š” Inno DB ์˜ ์„ธ์ปจ๋”๋ฆฌ ์ธ๋ฑ์Šค(Non-Clustering Index)์˜ ํŠน์ˆ˜ํ•œ ๊ตฌ์กฐ ๋•๋ถ„์ž…๋‹ˆ๋‹ค. Inno DB ์˜ ์„ธ์ปจ๋”๋ฆฌ ์ธ๋ฑ์Šค์˜ ๋ฆฌํ”„ ๋…ธ๋“œ์—๋Š” ํ•ด๋‹น ๋ ˆ์ฝ”๋“œ์˜ ๋ฐ์ดํ„ฐ ์ฃผ์†Œ๊ฐ€ ์•„๋‹Œ ํด๋Ÿฌ์Šคํ„ฐ๋ง ์ธ๋ฑ์Šค์˜ ๊ฐ’(PK)์„ ์ €์žฅํ•˜๋„๋ก ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ์„ธ์ปจ๋”๋ฆฌ ์ธ๋ฑ์Šค์ธ ๋ณตํ•ฉ ์ธ๋ฑ์Šค์˜ ๋ฆฌํ”„ ๋…ธ๋“œ์—๋Š” role_history ํ…Œ์ด๋ธ”์˜ PK ์ธ id ๊ฐ’์ด ์ €์žฅ๋˜์–ด ์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ง์ ‘์ ์ธ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ์—†์ด ์ธ๋ฑ์Šค๋งŒ์œผ๋กœ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜์—ฌ ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค๊ฐ€ ์ ์šฉ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ์ ์šฉ์œผ๋กœ ์ธํ•ด ์„ฑ๋Šฅ์ด 0.64 โ†’ 0.09 ๋กœ ์•ฝ 7๋ฐฐ ํ–ฅ์ƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์•„์ง ๋ˆˆ์— ๊ฑธ๋ฆฌ๋Š” ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค. Extra ํ•„๋“œ์— Using index ์ด์™ธ์—, ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ฌ๊ณ  ๋‹ค๋‹Œ Using temporary ์™€ Using filesort ๊ฐ€ ํ‘œ๊ธฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
โ€ข
Using temporary
โ—ฆ
๋ ˆ์ฝ”๋“œ๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๊ฑฐ๋‚˜ ์ •๋ ฌํ•  ๋•Œ ์ž„์‹œ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
โ—ฆ
์ฒ˜์Œ์—๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ์ƒ์„ฑ๋˜์—ˆ๋‹ค๊ฐ€, ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋ฐ์ดํ„ฐ์˜ ์–‘์ด ์ปค์ง€๋ฉด ๋””์Šคํฌ์— ์ €์žฅ๋˜์–ด ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โ€ข
Using filesort
โ—ฆ
์ธ๋ฑ์Šค๋กœ ์ •๋ ฌ๋˜์–ด ์žˆ์ง€ ์•Š์€ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.
์œ„์˜ ๋‘ ์ •๋ณด๋Š” ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ผ์œผํ‚ค๋Š” ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค. Using temporary ์™€ Using filesort ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์€ ๊ทธ๋ฃนํ™”/์ •๋ ฌ ์‹œ ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ์กฐ๊ฑด์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ ์ด๋ฒˆ ๊ฒฝ์šฐ์—์„œ๋Š” ์ธ๋ฑ์Šค ์ปฌ๋Ÿผ์„ ๋ณ€ํ˜•ํ•˜์—ฌ ์ธ๋ฑ์Šค๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๊ทธ๋ฃนํ™”์™€ ์ •๋ ฌ ์‹œ ์ด์šฉํ•˜๋Š” ์ปฌ๋Ÿผ์€ ์ธ๋ฑ์Šค๋กœ ์„ค์ •ํ•œ date_time ์ด ์•„๋‹ˆ๋ผ, ๋น„์ฆˆ๋‹ˆ์Šค ์ •์ฑ…์ƒ ๋‚ ์งœ๋กœ ๋ณ€ํ˜•์ด ํ•„์š”ํ•œ date(date_time) ์ž…๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ๋ณ€ํ˜•๋œ ์ปฌ๋Ÿผ์„ ๊ทธ๋ฃนํ™”/์ •๋ ฌํ•˜๊ธฐ ์œ„ํ•ด Using temporary ์™€ Using filesort ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

date ์ปฌ๋Ÿผ ์ถ”๊ฐ€

์ด์— ๋”ฐ๋ผ Using temporary ์™€ Using filesort ๋ฅผ ์—†์• ๊ธฐ ์œ„ํ•ด ๊ธฐ์กด date_time ์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ์ƒˆ๋กœ์šด date ์ปฌ๋Ÿผ์„ ๋งŒ๋“œ๋Š” ๋ฐ˜์ •๊ทœํ™”๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋น„๋ก ๋ฐ์ดํ„ฐ ์˜๋ฏธ๊ฐ€ ์ค‘๋ณต๋˜์–ด ์ €์žฅ๋˜๋Š” ๋‹จ์ ์ด ์žˆ์ง€๋งŒ, ์กฐํšŒ ์„ฑ๋Šฅ์ด ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ ๋” ์ค‘์š”ํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒˆ๋กœ ์ƒ์„ฑํ•œ date ์ปฌ๋Ÿผ์ด ํฌํ•จ๋œ ๋ณตํ•ฉ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
alter table role_history add date date; update role_history set date=date(date_time); create index role_history_index_role_id_date on role_history (role_id, date);
SQL
๋ณต์‚ฌ
๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ฃนํ™”์™€ ์ •๋ ฌํ•˜๋Š” ์ปฌ๋Ÿผ์„ ์ƒˆ๋กœ ์ƒ์„ฑํ•œ date ์ปฌ๋Ÿผ์œผ๋กœ ๋ณ€๊ฒฝํ•œ ๋’ค ์‹คํ–‰ ๊ณ„ํš์„ ์‚ดํŽด๋ณด๋ฉด,
select max(rolehistor0_.id)ascol_0_0_ from role_history rolehistor0_ where rolehistor0_.role_id=17 group by date order by date desc;
SQL
๋ณต์‚ฌ
๊ณ„์† ํ˜น์ฒ˜๋Ÿผ ๋‹ฌ๊ณ  ๋‹ค๋‹ˆ๋˜ Using temporary ์™€ Using filesort ๋ฅผ ๋“œ๋””์–ด ๋–ผ์–ด๋‚ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค! ๋˜ํ•œ ์„ฑ๋Šฅ๋„ 0.09 โ†’ 0.03 ์œผ๋กœ 3๋ฐฐ ๋” ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Backward index scan ์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ์ž‘์€ ํ˜น์ด ์ƒˆ๋กœ ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋น„์ฆˆ๋‹ˆ์Šค ์ •์ฑ… ์ƒ, ๋‚ ์งœ๋ฅผ ์ตœ์‹ ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜์—ฌ ์‘๋‹ตํ•˜๊ธฐ๋•Œ๋ฌธ์— ๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌ์„ ์ด์šฉํ•˜์˜€๊ณ , ์ด๋กœ ์ธํ•ด ์ธ๋ฑ์Šค๋ฅผ ๋’ค์—์„œ ๋ถ€ํ„ฐ ์ฝ๋Š” Backward index scan ์ด ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์—ญ์ˆœ ์ธ๋ฑ์Šค ์„ค์ •

MySQL ์—์„œ๋Š” ์ธ๋ฑ์Šค ์—ญ์ˆœ ์ •๋ ฌ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ 8.0 ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” ๋ฌธ๋ฒ•์ƒ์œผ๋กœ๋งŒ ์ง€์›์„ ํ•˜๊ณ  ์‹ค์ œ๋กœ๋Š” ์ง€์›๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ 8.0 ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” ์—ญ์ˆœ ์ธ๋ฑ์Šค ์ ์šฉ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์—ญ์ˆœ ์ธ๋ฑ์Šค์— ๋Œ€ํ•œ ๋”์šฑ ์ž์„ธํ•œ ๋‚ด์šฉ์€ MySQL Ascending index vs Descending index ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ์š”, ํ•ด๋‹น ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ์„ ์š”์•ฝํ•˜์ž๋ฉด, ์ธ๋ฑ์Šค ํŽ˜์ด์ง€ ๊ตฌ์กฐ๋Š” double linked list ์—ฌ์„œ ์•ž์—์„œ ์ฝ๋“  ์—ญ์ˆœ์œผ๋กœ ์ฝ๋“  ์„ฑ๋Šฅ์ด ๊ฐ™์„ ๊ฒƒ ๊ฐ™์€๋ฐ ์„ฑ๋Šฅ ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ์ด์œ ๋Š” 1. ํŽ˜์ด์ง€ ์ž ๊ธˆ์ด forward index scan ์— ์ ํ•ฉํ•œ ๊ตฌ์กฐ์ด๊ณ , 2. '์ธ๋ฑ์Šค ํŽ˜์ด์ง€ ๋‚ด'์—์„œ๋Š” ์ธ๋ฑ์Šค ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ์—ฐ๊ฒฐ๋œ ๊ตฌ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ forward index scan ๊ณผ backward index scan ์˜ ์„ฑ๋Šฅ ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ์ฟผ๋ฆฌ๊ฐ€ ํ•˜๋‚˜์˜ ์ธ๋ฑ์Šค ํŽ˜์ด์ง€์— ์ง‘์ค‘๋˜๋Š” ์ƒํ™ฉ์ธ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด ์ƒํ™ฉ์—์„œ ํŽ˜์ด์ง€ ์ž ๊ธˆ์„ ํš๋“ํ•˜๊ธฐ ์œ„ํ•œ ์“ฐ๋ ˆ๋“œ๋ผ๋ฆฌ์˜ ๊ฒฝํ•ฉ์ด ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ฐœ์ƒํ•˜์—ฌ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์˜ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
-- ์ธ๋ฑ์Šค: tid desc set @random_tid=floor(rand()*12994454); select tid from t1 where tid<=@random_tid order by tid DESC limit 50; -- ์ถœ์ฒ˜: https://tech.kakao.com/2018/06/19/mysql-ascending-index-vs-descending-index/ -- ์ธ๋ฑ์Šค: language, rental_datetime desc select title, rental_datetime from rentals where language = 'Italian' order by rental_datetime desc; -- ์ถœ์ฒ˜: https://medium.com/naver-cloud-platform/%EC%9D%B4%EB%A0%87%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EC%84%B8%EC%9A%94-mysql-8-0-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%8B%A0%EA%B7%9C-%EA%B8%B0%EB%8A%A5-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0-3-indexes-e32249e2dae5
SQL
๋ณต์‚ฌ
๋‘ ์ฟผ๋ฆฌ ๋ชจ๋‘ ์กฐ๊ฑด์ ˆ์—์„œ ํ•„ํ„ฐ๋ง๋˜์–ด ํ•˜๋‚˜์˜ ์ธ๋ฑ์Šค ํŽ˜์ด์ง€์— ์ง‘์ค‘๋˜๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ์ธ๋ฑ์Šค๋ฅผ ์ ์šฉํ•˜๋ ค๋Š” ์ฟผ๋ฆฌ์™€ ๋งŽ์ด ๋‹ฎ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ์˜ ์ฟผ๋ฆฌ๋„ role_id ๋กœ ์กฐ๊ฑด์ ˆ ํ•„ํ„ฐ๋ง์„ ํ•˜๊ธฐ๋•Œ๋ฌธ์— ํ•„ํ„ฐ๋ง๋œ role_id ๋ฅผ ๊ฐ€์ง„ ์ธ๋ฑ์Šค ํŽ˜์ด์ง€์— ์ง‘์ค‘๋˜๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ ์—ญ์ˆœ ์ธ๋ฑ์Šค๋ฅผ ์ ์šฉํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜์˜€์Šต๋‹ˆ๋‹ค.
create index role_history_index_role_id_date_desc on role_history (role_id, date desc);
SQL
๋ณต์‚ฌ
Backward index scan ์—†์ด ๊น”๋”ํ•˜๊ฒŒ ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์†๋„๋„ 0.03 โ†’ 0.02 ๋กœ ์•ฝ 50% ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋งˆ๋ฌด๋ฆฌ

MySQL ์˜ ์‹คํ–‰ ๊ณ„ํš์œผ๋กœ ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์ ์šฉ๋  ์ธ๋ฑ์Šค์™€ ์ตœ์ ํ™” ์˜ต์…˜์„ ํ™•์ธํ•˜๊ณ , ์ฟผ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง์„ ์ด์šฉํ•˜์—ฌ ์‹ค์ œ๋กœ ์‹คํ–‰๋œ ์ฟผ๋ฆฌ์˜ ์ˆ˜ํ–‰ ์†๋„์™€ ์†๋„์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ์ˆ˜๋ฅผ ํ™•์ธํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ณตํ•ฉ ์ธ๋ฑ์Šค์™€ ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค๋ฅผ ์ ์šฉํ•˜์—ฌ where + group by + order by ๊ฐ€ ํฌํ•จ๋œ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์˜ ์†๋„๋ฅผ ๊ฐœ์„ ํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ํ˜„์žฌ๋„ ์•„์‰ฌ์šด ์ ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋กœ ์ €์žฅํ•œ role id ์ปฌ๋Ÿผ๊ณผ date ๋Š” ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€ ๋†’์ง€ ์•Š์•„ ์ธ๋ฑ์Šค์˜ ํšจ์œจ์ด ์ƒ๋Œ€์ ์œผ๋กœ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ธ๋ฑ์Šค๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์—ฌ๋ถ„์˜ ์ธ๋ฑ์Šค ์ €์žฅ ๊ณต๊ฐ„(ํ†ต์ƒ ์•ฝ 10%)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ์˜ ๊ฐ€์žฅ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์€ ์œ„์™€ ๊ฐ™์ด ๋ณต์žกํ•œ ๊ธฐ์ˆ  ์ ์šฉ ์—†์ด๋„, ๋น„์ฆˆ๋‹ˆ์Šค ์ •์ฑ… ์ƒ์œผ๋กœ ์‰ฌ์šด ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๊ณ ๋ฏผํ•˜๊ณ  ์ ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(EO ๊น€๋ฒ”์ค€๋‹˜์˜ ์˜์ƒ์„ ์ฐธ๊ณ ํ•˜์˜€์Šต๋‹ˆ๋‹ค). ํ•˜์ง€๋งŒ ๋น„์ฆˆ๋‹ˆ์Šค ์ •์ฑ…์ƒ์œผ๋กœ ๋ถˆ๊ฐ€ํ”ผํ•˜๊ฒŒ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค๋ฉด ํ˜„์žฌ ํ…Œ์ด๋ธ”์—์„œ ์กฐํšŒํ•˜๋Š” ๋Œ€์‹ , ํ•ด๋‹น ์ฟผ๋ฆฌ์— ์ตœ์ ํ™”๋œ ์ปฌ๋Ÿผ์œผ๋กœ ์ƒˆ๋กœ์šด ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด ๋ฐ˜์ •๊ทœํ™”๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ๋„ ๊ณ ๋ คํ•ด๋ณผ ๋งŒํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ด ๋ฐฉ์‹ ๋˜ํ•œ ์ค‘๋ณต๋œ ์˜๋ฏธ์˜ ์ปฌ๋Ÿผ์ด ์—ฌ๋Ÿฟ ์กด์žฌํ•˜๊ฒŒ ๋˜๋‹ˆ, ํ”„๋กœ์ ํŠธ์˜ ์ž์›๋Ÿ‰์— ๋งž์ถฐ ์–ด๋–ค ๋ฐฉ์‹์ด ๊ฐ€์žฅ ํšจ์œจ์ ์ผ์ง€ ๊ณ ๋ฏผํ•ด๋ณด๊ณ  ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.