๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

MySQL

'์‹คํ–‰๊ณ„ํš์—์„œ ๋ฌด์—‡์„ ์ค‘์š”ํ•˜๊ฒŒ ๋ณผ ๊ฒƒ์ธ๊ฐ€?' - ๊ฐœ์ธ์ ์ธ ํ†ต์ฐฐ

Real MySQL 8.0 10์žฅ ์‹คํ–‰๊ณ„ํš์„ 150๋งŒ๊ฐœ์˜ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•ด ๊ณต๋ถ€ํ•˜๋ฉฐ ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.
"์‹คํ–‰ ๊ณ„ํš์„ ์–ด๋–ป๊ฒŒ ์ฝ์–ด์•ผ ํ•˜๋Š”์ง€, ๋ฌด์—‡์„ ์ฝ์–ด์•ผ ํ•˜๋Š”์ง€?" ์— ๋Œ€ํ•ด ์ œ ๊ฐœ์ธ์ ์ธ ์˜๊ฒฌ์ด ๋“ค์–ด๊ฐ”์Œ์„ ๋ฐํžˆ๋ฉฐ, ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ์žˆ์Œ์„ ๋ฏธ๋ฆฌ ์–‘ํ•ด ๊ตฌํ•ฉ๋‹ˆ๋‹ค.

1. ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ๋•Œ ๊ณ ๋ คํ•˜๋Š” ๊ธฐ์ค€

์ €๋Š” ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ์ปฌ๋Ÿผ์„ ์„ ํƒํ•  ๋•Œ ๋‹ค์Œ 3๊ฐ€์ง€ ๊ธฐ์ค€์„ ์ฃผ๋กœ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.

* ์ถ”๊ฐ€๋กœ, ์ธ๋ฑ์Šค ์„ค์ • ์‹œ ์ฃผ์˜ํ•  ์ ๋“ค์€ ํ•ด๋‹น ๋ชฉ์ฐจ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚จ์œผ๋กœ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

 

โ“ ์นด๋””๋„๋ฆฌํ‹ฐ(Cardinality)๊ฐ€ ๋†’์€ ์ปฌ๋Ÿผ์ธ๊ฐ€?

  • ์นด๋””๋„๋ฆฌํ‹ฐ๋Š” ํ•ด๋‹น ์ปฌ๋Ÿผ์˜ ๊ณ ์œ  ๊ฐ’ ์ˆ˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • InnoDB ๊ฐ€ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฝ์„ ๋•Œ, ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€ ๋†’์„์ˆ˜๋ก ๋น ๋ฅด๊ฒŒ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€ ๋†’์€ ์ปฌ๋Ÿผ์€ ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ๋•Œ ์šฐ์„  ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.

โ“‘ UPDATE/DELETE ์ฟผ๋ฆฌ์˜ WHERE ์ ˆ์— ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ์ธ๊ฐ€?

  • UPDATE๋‚˜ DELETE ์ฟผ๋ฆฌ์—์„œ WHERE ์ ˆ์— ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๊ฐ€ ์—†์œผ๋ฉด InnoDB๊ฐ€ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฐพ์œผ๋ฉด์„œ ๋ถˆํ•„์š”ํ•œ ๋ ˆ์ฝ”๋“œ์— ๋ฐฐํƒ€ ๋ฝ์ด ๊ฑธ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ, WHERE ์ ˆ์—์„œ ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ์ด๋ผ๋ฉด ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๋ ˆ์ฝ”๋“œ์— ๋ฝ์ด ๊ฑธ๋ฆฌ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

โ“’ ๋ฉ€ํ‹ฐ ์ปฌ๋Ÿผ ์ธ๋ฑ์Šค ์„ค์ • ์‹œ, ๋™๋“ฑ ์กฐ๊ฑด์œผ๋กœ ๋น„๊ต๋˜๋Š” ์ปฌ๋Ÿผ์„ ์•ž ์ˆœ์„œ์— ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฉ€ํ‹ฐ ์ปฌ๋Ÿผ ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ๋•Œ๋Š” ๋™๋“ฑ ์กฐ๊ฑด(= ๋น„๊ต, IN์ ˆ)์œผ๋กœ ์ž์ฃผ ๋น„๊ต๋˜๋Š” ์ปฌ๋Ÿผ์„ ์•ž ์ˆœ์„œ์— ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉ€ํ‹ฐ ์ปฌ๋Ÿผ ์ธ๋ฑ์Šค์ด WHERE ์ ˆ์˜ ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ๋  ๊ฒฝ์šฐ, ๋™๋“ฑ ์กฐ๊ฑด์—์„œ ์ธ๋ฑ์Šค๋Š” ๋ฒ”์œ„ ๊ฒฐ์ • ์กฐ๊ฑด์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, ๋ฒ”์œ„ ์กฐ๊ฑด์ด ๋จผ์ € ๋‚˜์˜ค๊ณ  ๊ทธ ์ดํ›„์— ๋™๋“ฑ ์กฐ๊ฑด์ด ์˜ค๋Š” ๊ฒฝ์šฐ, ๋™๋“ฑ ์กฐ๊ฑด์€ ๋‹จ์ˆœํ•œ ํ•„ํ„ฐ๋ง ์—ญํ• ์— ๊ทธ์น˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด์ฒ˜๋Ÿผ ์ธ๋ฑ์Šค๋ฅผ ์„ค์ • ํ•  ๋•Œ ์—ฌ๋Ÿฌ ๊ธฐ์ค€์„ ๊ณ ๋ คํ•˜์ง€๋งŒ, ์‹ค์ œ ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์€ ์‹คํ–‰ ๊ณ„ํš์„ ํ†ตํ•ด ์ง์ ‘ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์‹คํ–‰ ๊ณ„ํš์„ ๋ถ„์„ํ•˜๋ฉด ์„ค์ •ํ•œ ์ธ๋ฑ์Šค๊ฐ€ ์ œ๋Œ€๋กœ ํ™œ์šฉ๋˜๋Š”์ง€, ์ฟผ๋ฆฌ๊ฐ€ ์ตœ์ ํ™”๋˜์–ด ์žˆ๋Š”์ง€๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

2. ์‹คํ—˜ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ๋ฐ ์‹คํ—˜ ์†Œ๊ฐœ

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ์‹คํ–‰ ๊ณ„ํš์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜๊ฒŒ ๋˜์—ˆ๊ณ , ์‹ค์ œ ์‹คํ–‰ ๊ณ„ํš์„ ์ฝ๊ณ  ํ•ด์„ํ•˜๋Š” ๋ฐฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰ ๊ณ„ํš์—์„œ ๋ฌด์—‡์„ ์ค‘์ ์ ์œผ๋กœ ๋ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ง์ ‘ ๋ถ„์„ํ–ˆ๊ณ , ์ œ๊ฐ€ ๋Š๋‚€ ์ ๊ณผ ๊นจ๋‹ฌ์€ ๋‚ด์šฉ์„ ๊ณต์œ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

 

ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด letter ํ…Œ์ด๋ธ”์—๋Š” ์•ฝ 150๋งŒ ๊ฑด์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ, reply ํ…Œ์ด๋ธ”์—๋Š” ์•ฝ 10๋งŒ ๊ฑด์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์‹คํ—˜์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

letter ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ ๊ฐœ์ˆ˜
reply ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ ๊ฐœ์ˆ˜

 

์กฐํšŒ ๋Œ€์ƒ์€ ํŠน์ • ์œ ์ €๊ฐ€ ์ง€๋‚œ ํ•œ ๋‹ฌ ๋™์•ˆ ์ž‘์„ฑํ•œ ํŽธ์ง€ ์ค‘ ๋ฐœํ–‰๋œ ํŽธ์ง€์ด๋ฉฐ, ๊ฒฐ๊ณผ๋Š” ์ƒ์„ฑ์ผ(created_at) ๊ธฐ์ค€์œผ๋กœ ๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌํ•˜์—ฌ ์ตœ์‹  3๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ๋งŒ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

SELECT l.*
FROM letter l
JOIN reply r ON l.letter_id = r.letter_id
WHERE l.created_at BETWEEN '2024-10-01 00:00:18.000000' AND '2024-11-01 00:00:18.000000'
    AND l.published = true 
    AND l.user_id = UUID_TO_BIN('6f296420-23c1-4e0d-a9cb-a7cb85b1c76c')
ORDER BY l.created_at DESC
LIMIT 3;

 

 

MySQL์˜ ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” ํ†ต๊ณ„ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์‹คํ–‰ ๊ณ„ํš์„ ์ˆ˜๋ฆฝํ•ฉ๋‹ˆ๋‹ค. ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ์˜ ์ตœ์‹  ํ†ต๊ณ„ ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ๋‘ ํ…Œ์ด๋ธ”์˜ ํ†ต๊ณ„ ์ •๋ณด๋ฅผ ์ตœ์‹ ํ™” ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

ANALYZE TABLE letter;
ANALYZE TABLE reply;

 

์ด์ œ EXPLAIN ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ์‹คํ–‰ ๊ณ„ํš์„ ํ™•์ธํ•˜๊ณ , ๊ฐ ์ปฌ๋Ÿผ์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋ฅผ ํ•ด์„ํ•˜๋ฉด์„œ ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•  ๋ฐฉ๋ฒ•์„ ๊ณ ๋ฏผํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ด๋ธ” ํ˜•ํƒœ์˜ ์‹คํ–‰ ๊ณ„ํš ๊ฒฐ๊ณผ

 

์‹คํ–‰ ๊ณ„ํš์„ ๊ณต๋ถ€ํ•œ ๊ฒฐ๊ณผ, ์‹คํ–‰ ๊ณ„ํš์—์„œ ์ค‘์š”ํ•˜๊ฒŒ ๋ด์•ผํ•˜๋Š” ์ปฌ๋Ÿผ์€ type / key / key_len / rows / filtered / Extra ์ž…๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

3. Table ํ˜•ํƒœ์˜ ์‹คํ–‰ ๊ณ„ํš ๋ถ„์„

โ–ถ type ์ปฌ๋Ÿผ: ๊ฐ ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์ฝ์—ˆ๋Š”์ง€

  • letter ํ…Œ์ด๋ธ” (table ์—์„œ l) : ref
    • ref ๋Š” ์กฐ์ธ์˜ ์ˆœ์„œ์™€ ์ธ๋ฑ์Šค์˜ ์ข…๋ฅ˜์— ๊ด€๊ณ„์—†์ด ๋™๋“ฑ ์กฐ๊ฑด์œผ๋กœ ๊ฒ€์ƒ‰ํ–ˆ๋‹ค๋Š” ๊ฒƒ์œผ๋กœ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
  • reply ํ…Œ์ด๋ธ” (table ์—์„œ r) : eq_ref
    • eq_ref ๋Š” ์กฐ์ธ๋˜๋Š” ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ๊ณ„ํš์—์„œ๋งŒ ํ‘œ์‹œ๋˜๋ฉฐ, ์ฒซ ๋ฒˆ์งธ ์ฝ์€ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ ๊ฐ’์„ ์ด์šฉํ•ด ๋‘ ๋ฒˆ์งธ ํ…Œ์ด๋ธ”์„ PK๋‚˜ ์œ ๋‹ˆํฌ ํ‚ค๋กœ ๋™๋“ฑ ์กฐ๊ฑด ๊ฒ€์ƒ‰ํ•  ๋•Œ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
    • eq_ref ์—์„œ ๋‘ ๋ฒˆ์งธ ํ…Œ์ด๋ธ”์€ ๋ฐ˜๋“œ์‹œ 1๊ฑด์˜ ๋ ˆ์ฝ”๋“œ๋งŒ ๋ฐ˜ํ™˜๋˜๋ฏ€๋กœ ๋งค์šฐ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

Real MySQL ์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์œผ๋กœ ์„ฑ๋Šฅ์ด ๋น ๋ฅด๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.(๋’ค๋กœ ๊ฐˆ์ˆ˜๋ก ๋Š๋ ค์ง)

const → eq_ref → ref → fulltext → ref_or_null → unique_subquery → index_subquery → range → index_merge → index → ALL

 

์—ฌ๊ธฐ์„œ, ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์žˆ๋Š” ALL ์ด ์ธ๋ฑ์Šค๋ฅผ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•œ ํ…Œ์ด๋ธ” ํ’€ ์Šค์บ”์ด๋ฉฐ์ด๊ณ , index ๊ฐ€ ์ธ๋ฑ์Šค ํ’€ ์Šค์บ”์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์‹คํ–‰ ๊ณ„ํš์ด ํ•ด๋‹น ๊ฐ’์„ ๊ฐ€์ง„๋‹ค๋ฉด ์ธ๋ฑ์Šค ๋ฐ ์ฟผ๋ฆฌ ์ˆ˜์ •์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

 

โ–ถ key ์ปฌ๋Ÿผ: ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฝ์„ ๋•Œ ์‚ฌ์šฉ๋œ ์ธ๋ฑ์Šค

MySQL์—์„œ๋Š” ํ…Œ์ด๋ธ”์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธ๋ฑ์Šค๊ฐ€ ์žˆ์–ด๋„ ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ ๋‹จ ํ•˜๋‚˜์˜ ์ธ๋ฑ์Šค๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ, key ์ปฌ๋Ÿผ์€ ํ•ญ์ƒ 1๊ฐœ์˜ key ๋งŒ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ์ฟผ๋ฆฌ์—์„œ๋Š” ๋‹ค์Œ ์ธ๋ฑ์Šค๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • letter ํ…Œ์ด๋ธ”: user_id (์™ธ๋ž˜ ํ‚ค)
  • reply ํ…Œ์ด๋ธ”: letter_id (์œ ๋‹ˆํฌ ํ‚ค์ด์ž ์™ธ๋ž˜ ํ‚ค)

key ์ปฌ๋Ÿผ์„ ํ†ตํ•ด ์˜๋„๋œ ์ธ๋ฑ์Šค๊ฐ€ ์“ฐ์˜€๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

โ–ถ key_len ์ปฌ๋Ÿผ: ๋ฉ€ํ‹ฐ ์ปฌ๋Ÿผ ์ธ๋ฑ์Šค์—์„œ ๋ช‡ ๊ฐœ์˜ ์ปฌ๋Ÿผ์ด ์‚ฌ์šฉ๋˜์—ˆ๋Š”์ง€

  • ์ด๋ฒˆ ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉ๋œ letter ํ…Œ์ด๋ธ”์˜ FK(user_id)์™€ reply ํ…Œ์ด๋ธ”์˜ UK(letter_id)๋Š” UUID ํƒ€์ž…์œผ๋กœ 16๋ฐ”์ดํŠธ์ž…๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ, key_len ๊ฐ’์ด 16์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋ฉฐ, UUID ์ปฌ๋Ÿผ ์ „์ฒด๊ฐ€ ์ธ๋ฑ์Šค ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ๋˜์—ˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

key_len ์ปฌ๋Ÿผ์„ ํ†ตํ•ด ๋ฉ€ํ‹ฐ ์ปฌ๋Ÿผ ์ธ๋ฑ์Šค์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š์€ ์ปฌ๋Ÿผ์„ ๊ตฌ๋ถ„ํ•ด์„œ ๋ถˆํ•„์š”ํ•œ ์ปฌ๋Ÿผ์„ ๋ฉ€ํ‹ฐ ์ปฌ๋Ÿผ ์ธ๋ฑ์Šค์—์„œ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

โ–ถ rows ์ปฌ๋Ÿผ: InnoDB ๊ฐ€ ์ฟผ๋ฆฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ํ–‰์„ ์ฝ์–ด์•ผ ํ•˜๋Š”์ง€

  • ์ด๋ฒˆ ์ฟผ๋ฆฌ์—์„œ ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” letter ํ…Œ์ด๋ธ”์—์„œ 17๊ฐœ ํ–‰์„ ์ฝ์–ด์•ผ ํ•œ๋‹ค๊ณ  ์˜ˆ์ธกํ–ˆ์Šต๋‹ˆ๋‹ค.

 

โ–ถ filtered ์ปฌ๋Ÿผ: MySQL์—”์ง„์ด InnoDB๊ฐ€ ์ฝ์€ ๋ ˆ์ฝ”๋“œ ์ค‘ ์ธ๋ฑ์Šค๋ฅผ ํ™œ์šฉํ•˜์ง€ ์•Š๋Š” ์ปฌ๋Ÿผ์— ์˜ํ•ด ํ•„ํ„ฐ๋ง๋œ ๋ ˆ์ฝ”๋“œ์˜ ๋น„์œจ

letter ํ…Œ์ด๋ธ”์—์„œ ์ฟผ๋ฆฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ฝ์–ด์•ผ ํ•  ํ–‰์˜ ์ˆ˜(rows)๋Š” 17๊ฐœ์ž…๋‹ˆ๋‹ค.

  • ์ด ์ค‘ l.created_at ์กฐ๊ฑด๊ณผ l.published = true ์กฐ๊ฑด์„ ํ†ตํ•ด ํ•„ํ„ฐ๋ง๋˜์–ด reply ํ…Œ์ด๋ธ”์— JOIN ๋  ํ–‰์˜ ๊ฐœ์ˆ˜๋Š” 17 * 0.056 ์ธ ์•ฝ 1๊ฐœ๋กœ ์˜ˆ์ธก๋ฉ๋‹ˆ๋‹ค.

โ€ป rows์™€ filtered์˜ ์ค‘์š”์„ฑ

์ด๋ฒˆ ์ฟผ๋ฆฌ์—์„œ๋Š” rows์™€ filtered ๊ฐ’์ด ๋ฌธ์ œ๊ฐ€ ์—†์–ด ๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ œ๊ฐ€ ์ด ๋‘ ์ปฌ๋Ÿผ์„ ์ค‘์š”ํ•˜๊ฒŒ ๋ณด๋Š” ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • rows ๊ฐ’์ด ํฌ๊ณ , filtered ๊ฐ’์ด ๋‚ฎ์€ ๊ฒฝ์šฐ๋Š” ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋งŽ์€ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฝ์—ˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด rows = 97,000, filtered = 10 ์ด ๋‚˜์™”๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

  • InnoDB๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด 97,000๊ฑด์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋‚˜ WHERE ์กฐ๊ฑด์„ ํ†ตํ•ด ํ•„ํ„ฐ๋ง๋œ ๋ ˆ์ฝ”๋“œ๋Š” 9,700๊ฑด(97,000 * 0.1)์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์•ฝ 87,300๊ฑด์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ฝ์€ ๊ฒƒ์ด๋ฏ€๋กœ, ์ด ๊ฒฝ์šฐ์—๋Š” ์ฟผ๋ฆฌ ํŠœ๋‹ ๋˜๋Š” ์ธ๋ฑ์Šค ์ˆ˜์ •์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

โ–ถ Extra ์ปฌ๋Ÿผ: ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ๊ณผ ๊ด€๋ จ๋œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ œ๊ณต

๋จผ์ € letter ํ…Œ์ด๋ธ”์˜ Extra ์ปฌ๋Ÿผ์„ ํ•ด์„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

Using index condition;

  • ์ด ๊ฐ’์€ ์ธ๋ฑ์Šค์— ํฌํ•จ๋œ ์ปฌ๋Ÿผ์ด๋ผ๋ฉด InnoDB(์Šคํ† ๋ฆฌ์ง€ ์—”์ง„)์œผ๋กœ ์ „๋‹ฌํ•˜์—ฌ ์ตœ๋Œ€ํ•œ InnoDB์—์„œ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฑธ๋Ÿฌ์„œ MySQL ์—”์ง„์— ์ฃผ๋„๋ก ์ตœ์ ํ™”๋œ ๊ธฐ๋Šฅ์œผ๋กœ MySQL ์€ 5.6 ๊ธฐ์ค€์œผ๋กœ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
  • ์ฆ‰, ํ•„ํ„ฐ๋ง ์ž‘์—…์„ MySQL ์—”์ง„์—์„œ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ , InnoDB์—์„œ ์ฒ˜๋ฆฌํ•จ์œผ๋กœ์จ ๋””์Šคํฌ I/O๋ฅผ ์ค„์ด๊ณ  ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค.

// ์ธ๋ฑ์Šค
INDEX full_name (last_name, first_name)

// ์ฟผ๋ฆฌ
WHERE last_name = "์ข…ํ˜" and first_name LIKE "%์•ˆ";

์ฒ˜๋ฆฌ ๊ณผ์ •

  • ์ด ์ฟผ๋ฆฌ์—์„œ InnoDB๋Š” last_name = '์ข…ํ˜' ์กฐ๊ฑด์„ ์ธ๋ฑ์Šค(full_name)๋ฅผ ํ†ตํ•ด ๋น ๋ฅด๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋‚˜ first_name LIKE '%์•ˆ' ์กฐ๊ฑด์€ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด MySQL 5.5 ๋ฒ„์ „ ์ดํ•˜์—์„œ๋Š” MySQL ์—”์ง„์ด ์ง์ ‘ ํ•„ํ„ฐ๋ง์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด ๊ฒฝ์šฐ, InnoDB๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๋ ˆ์ฝ”๋“œ๋“ค์„ MySQL ์—”์ง„์ด ๋‹ค์‹œ ๋””์Šคํฌ I/O๋ฅผ ํ†ตํ•ด ํ•„ํ„ฐ๋งํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋น„ํšจ์œจ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค ์ปจ๋””์…˜ ํ‘ธ์‹œ๋‹ค์šด(MySQL 5.6 ์ด์ƒ ์ตœ์ ํ™”)

  • ํ•˜์ง€๋งŒ, InnoDB ๊ฐ€ last_name ์„ ์ฝ๊ธฐ ์œ„ํ•ด full_name ์ธ๋ฑ์Šค๋ฅผ ์ฝ์œผ๋ฉฐ first_name ๋„ ๊ฐ™์ด ํ•„ํ„ฐ๋ง ํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์–ด์ฐจํ”ผ full_name ์ธ๋ฑ์Šค๋ฅผ ์ฝ์„ํ…Œ๋‹ˆ๊นŒ์š”.
  • ์ฆ‰, ์ธ๋ฑ์Šค์— ํฌํ•จ๋œ ํ•„๋“œ๋ผ๋ฉด InnoDB ๋กœ ์ „๋‹ฌํ•ด์„œ ์ตœ๋Œ€ํ•œ InnoDB ๊ฐ€ ๊ฑธ๋Ÿฌ๋‚ผ ์ˆ˜ ์žˆ๋„๋ก ์ธ๋ฑ์Šค ์ปจ๋””์…˜ ํ‘ธ์‹œ๋‹ค์šด ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ์ธ๋ฑ์Šค ์กฐ๊ฑด์„ ๋‚ด๋ฆฌ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋””์ŠคํฌI/O ๋ฅผ ์ค„์ด๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

Using where;

์ด ๊ฐ’์€ MySQL์—”์ง„์—์„œ ํ•„ํ„ฐ๋ง ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ๊ฒฝ์šฐ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ์ด Using where ์ด ์„ฑ๋Šฅ์ƒ ์ข‹์€์ง€๋Š” filtered ์ปฌ๋Ÿผ์„ ๊ฐ™์ด ๋ณด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” filtered ๊ฐ€ 5%์ด๋‹ˆ, 17(rows) * 0.05 ๋ฅผ ๊ณฑํ•œ ๊ฐ’์ธ ์•ฝ 1๊ฑด์ด WHERE ์กฐ๊ฑด(ํ•„ํ„ฐ๋ง ์ž‘์—…)์˜ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ์ฆ‰, InnoDB ์€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฝ์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

 

Using filesort;

์ด ๊ฐ’์€ ORDER BY ๊ฐ€ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•  ๋•Œ ํ‘œ์‹œ๋˜๋ฉฐ, ORDER BY๊ฐ€ ์‚ฌ์šฉ๋œ ์ฟผ๋ฆฌ์—์„œ๋งŒ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. Real MySQL ์—์„œ๋Š” ORDER BY๋ฅผ ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ถ”๊ฐ€ CPU์—ฐ์‚ฐ๊ณผ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰, ๋””์Šคํฌ ์ž…์ถœ๋ ฅ์„ ์ฆ๊ฐ€์‹œํ‚ค๊ธฐ๋ฏ€๋กœ ์ฟผ๋ฆฌ๋ฅผ ํŠœ๋‹ํ•˜๊ฑฐ๋‚˜ ์ธ๋ฑ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

 

๊ฒฐ๊ตญ, Using filesort ๋Š” Extra ์ปฌ๋Ÿผ์—์„œ ์ œ๊ฑฐํ•ด์ฃผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

4. Table ํ˜•ํƒœ์˜ ์‹คํ–‰ ๊ณ„ํš ๋ถ„์„์— ๋Œ€ํ•œ ๊ฒฐ๋ก 

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

  • key ์™€ key_len ์„ ํ†ตํ•ด ์˜๋„๋œ ์ธ๋ฑ์Šค๊ฐ€ ์“ฐ์ด๋Š”์ง€
  • type ์„ ํ†ตํ•ด ์ธ๋ฑ์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ์“ฐ์ด๋Š”์ง€
  • rows ์™€ filtered ๋ฅผ ํ†ตํ•ด ๋ถˆํ•„์š”ํ•œ ํ–‰์„ ๋งŽ์ด ์ฝ์ง€๋Š” ์•Š๋Š”์ง€
  • Extra ์˜ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ฟผ๋ฆฌ์˜ ์ถ”๊ฐ€์ ์ธ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•œ์ง€

๋”ฐ๋ผ์„œ, ํ…Œ์ด๋ธ” ํ˜•ํƒœ์˜ ์‹คํ–‰ ๊ณ„ํš์—์„œ๋Š” ์ด ์ฃผ์š” ์ปฌ๋Ÿผ๋“ค์„ ์ฃผ์˜ ๊นŠ๊ฒŒ ๋ถ„์„ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

 

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

 

5. Tree ํ˜•ํƒœ์˜ ์‹คํ–‰ ๊ณ„ํš ๋ถ„์„

1. -> Limit: 3 row(s)  (cost=24.6 rows=3) (actual time=1.27..1.28 rows=3 loops=1)
2.     -> Nested loop inner join  (cost=24.6 rows=20) (actual time=1.27..1.28 rows=3 loops=1)
3.         -> Sort: l.created_at DESC  (cost=17.6 rows=20) (actual time=1.24..1.24 rows=3 loops=1)
4.             -> Filter: ((l.published = true) and (l.created_at between '2024-10-01 00:00:18.000000' and '2024-11-01 00:00:18.000000'))  (cost=17.6 rows=20) (actual time=1.19..1.21 rows=17 loops=1)
5.                 -> Index lookup on l using FK9tgknmmyr2kafs9bvfw5k9n84 (user_id=uuid_to_bin('95c2eeac-62fe-4d8e-9cb5-5f05be6d7df7')), with index condition: (l.user_id = <cache>(uuid_to_bin('95c2eeac-62fe-4d8e-9cb5-5f05be6d7df7')))  (cost=17.6 rows=20) (actual time=1.17..1.18 rows=20 loops=1)
6.         -> Single-row covering index lookup on r using UK6ln872eudt3ku5rk8vlj43f0r (letter_id=l.letter_id)  (cost=1.02 rows=1) (actual time=0.0117..0.0117 rows=1 loops=3)

 

explain analyze ์˜ TREE ํฌ๋งท์˜ ์‹คํ–‰ ์ˆœ์„œ๋Š” ๋‹ค์Œ ๊ธฐ์ค€์œผ๋กœ ์ฝ์Šต๋‹ˆ๋‹ค.

  • ๋“ค์—ฌ์“ฐ๊ธฐ๊ฐ€ ๊ฐ™์€ ๋ ˆ๋ฒจ์—์„œ๋Š” ์ƒ๋‹จ์— ์œ„์น˜ํ•œ ๋ผ์ธ์ด ๋จผ์ € ์‹คํ–‰
  • ๋“ค์—ฌ์“ฐ๊ธฐ๊ฐ€ ๋‹ค๋ฅธ ๋ ˆ๋ฒจ์—์„œ๋Š” ๊ฐ€์žฅ ์•ˆ์ชฝ์— ์œ„์น˜ํ•œ ๋ผ์ธ์ด ๋จผ์ € ์‹คํ–‰

๋”ฐ๋ผ์„œ, ์œ„ ์‹คํ–‰ ๊ณ„ํš์€ 5 → 4 → 3 → 6 → 2 → 1 ์ˆœ์„œ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

 

โ–ถ Tree ํฌ๋งท์˜ ์ฃผ์š” ์ง€ํ‘œ ์„ค๋ช…

actual time / rows / loops ์— ๋Œ€ํ•œ ๊ฐœ๋…์„ 6๋ฒˆ ๋ผ์ธ๊ณผ ํ•จ๊ป˜ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

actual time (์‹ค์ œ ์†Œ์š”๋œ ์‹œ๊ฐ„, ms)

  • actual time=0.0117..0.0117 ์—์„œ ์ฒซ ๋ฒˆ์งธ ๊ฐ’(0.0117ms)์€ ์ฒซ ๋ฒˆ์งธ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ๊ฑธ๋ฆฐ ํ‰๊ท  ์‹œ๊ฐ„, ๋‘ ๋ฒˆ์งธ ๊ฐ’(0.0117ms)์€ ๋งˆ์ง€๋ง‰ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ๊ฑธ๋ฆฐ ํ‰๊ท  ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.

rows (์ฒ˜๋ฆฌํ•œ ๋ ˆ์ฝ”๋“œ ๊ฑด์ˆ˜)

  • rows=1 ์€ ํ•ด๋‹น ๋ผ์ธ์„ ์‹คํ–‰ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•œ ํ…Œ์ด๋ธ”์˜ ํ‰๊ท  ๋ ˆ์ฝ”๋“œ ๊ฑด์ˆ˜

loops (๋ฐ˜๋ณต ํšŸ์ˆ˜)

  • ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฐพ๋Š” ์ž‘์—…์ด ๋ฐ˜๋ณต๋œ ํšŸ์ˆ˜์ž…๋‹ˆ๋‹ค. letter_id=l.letter_id ๋ฅผ ํ†ตํ•ด ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฐพ๋Š” ์ž‘์—…์ด 3๋ฒˆ ๋ฐ˜๋ณต๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ actual time๊ณผ rows๋ฅผ ํ‰๊ท  ์‹œ๊ฐ„๊ณผ ํ‰๊ท  ๋ ˆ์ฝ”๋“œ ์ˆ˜๋กœ ์„ค๋ช…ํ•œ ์ด์œ ๋Š” loops ๊ฐ’์ด 1 ์ด์ƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, reply ํ…Œ์ด๋ธ”์—์„œ l.letter_id์™€ ์ผ์น˜ํ•˜๋Š” ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฐพ๋Š” ์ž‘์—…์ด ์ด 3๋ฒˆ ๋ฐ˜๋ณต๋˜์—ˆ๊ณ , ๋งค๋ฒˆ ์ฒซ ๋ฒˆ์งธ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ํ‰๊ท  0.0117ms๊ฐ€ ์†Œ์š”๋˜์—ˆ์œผ๋ฉฐ, ๋งˆ์ง€๋ง‰ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ๋„ ํ‰๊ท  0.0117ms๊ฐ€ ๊ฑธ๋ฆฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ๋ฐ˜๋ณต ์‹คํ–‰(loops)์ด ์žˆ์„ ๋•Œ๋Š” actual time๊ณผ rows ๊ฐ’์ด ๊ฐ ๋ฐ˜๋ณต์˜ ํ‰๊ท ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค๋Š” ์ ์„ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

โ–ถ Tree ํฌ๋งท์—์„œ Using filesort ๋ถ„์„

์ด์ œ ์‹คํ–‰ ๊ณ„ํš์˜ 3๋ฒˆ ๋ผ์ธ์—์„œ Using filesort ๊ฐ€ ๋ฐœ์ƒํ•œ ๋ถ€๋ถ„์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Sort: l.created_at DESC  (cost=12.1 rows=17) (actual time=0.349..0.35 rows=11 loops=1)

 ํ•ด๋‹น ๋ผ์ธ์„ ๋ณด๋‹ˆ ์ •๋ ฌํ•˜๋Š”๋ฐ 0.3ms ๊ฐ€ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ๋งŽ์€ ๋ถ€ํ•˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ์š”. ๊ทธ ์›์ธ์— ๋Œ€ํ•ด ๋ถ„์„ํ•ด๋ดค์Šต๋‹ˆ๋‹ค.

 

์ฟผ๋ฆฌ์— ORDER BY ๊ฐ€ ์‚ฌ์šฉ๋˜๋ฉด ๋ฐ˜๋“œ์‹œ 3๊ฐ€์ง€ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋กœ ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค.

  • ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•œ ์ •๋ ฌ → Extra ๋ณ„๋„ ํ‘œ๊ธฐ ์—†์Œ
    • ๋ฐ˜๋“œ์‹œ ORDER BY์— ๋ช…์‹œ๋œ ์ปฌ๋Ÿผ์ด ์ œ์ผ ๋จผ์ € ์ฝ๋Š” ํ…Œ์ด๋ธ”์— ์†ํ•˜๊ณ , ORDER BY ์ˆœ์„œ๋Œ€๋กœ ์ƒ์„ฑ๋œ ์ธ๋ฑ์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์ฒซ ๋ฒˆ์งธ๋กœ ์ฝ๋Š” ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์— ๋Œ€ํ•œ WHERE ์กฐ๊ฑด์ด ์žˆ๋‹ค๋ฉด, ๊ทธ ์กฐ๊ฑด๊ณผ ORDER BY๋Š” ๊ฐ™์€ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • B-Tree ๊ณ„์—ด์ด ์•„๋‹Œ R-Tree(๊ณต๊ฐ„ ์ธ๋ฑ์Šค) / ์ „๋ฌธ ๊ฒ€์ƒ‰ ์ธ๋ฑ์Šค / ํ•ด์‹œ ์ธ๋ฑ์Šค์—์„œ๋Š” ์ด ๋ฐฉ๋ฒ• ์‚ฌ์šฉ ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • ์กฐ์ธ์—์„œ ๋“œ๋ผ์ด๋น™ ํ…Œ์ด๋ธ”๋งŒ ์ •๋ ฌ → Using filesort
    • '์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•œ ์ •๋ ฌ'์˜ ์ฐจ์„ ์ฑ…์œผ๋กœ ์กฐ์ธ์—์„œ ์ฒซ ๋ฒˆ์งธ๋กœ ์ฝํžˆ๋Š” ํ…Œ์ด๋ธ”์˜ ์นผ๋Ÿผ๋งŒ์œผ๋กœ ORDER BY ์ ˆ์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์กฐ์ธ์—์„œ ์กฐ์ธ ๊ฒฐ๊ณผ๋ฅผ ์ž„์‹œ ํ…Œ์ด๋ธ”๋กœ ์ €์žฅ ํ›„ ์ •๋ ฌ → Using temporary; Using filesort ๊ฐ€ ํ‘œ์‹œ
    • ์ •๋ ฌํ•ด์•ผ ํ•˜๋Š” ๋ ˆ์ฝ”๋“œ ๊ฑด์ˆ˜๊ฐ€ ๊ฐ€์žฅ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๋Š๋ฆฐ ์ •๋ ฌ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
    • Using temporary; ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋‚˜ ๋””์Šคํฌ์—์„œ ์ž„์‹œํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•ด์„œ ์ •๋ ฌ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ, ์ €๋Š” 2๋ฒˆ์งธ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์ธ '์กฐ์ธ์—์„œ ๋“œ๋ผ์ด๋น™ ํ…Œ์ด๋ธ”๋งŒ ์ •๋ ฌ' ์ด ์ ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ ์ตœ์•…์˜ ์ •๋ ฌ ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋“œ๋ผ์ด๋น™ ํ…Œ์ด๋ธ”์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋งŽ๋‹ค๋ฉด ์ •๋ ฌํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— EXPLAIN ANALYZE ๋กœ ์‹ค์ œ ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ์‹œ๊ฐ„์„ ํŒŒ์•…ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

6. ๊ฒฐ๋ก : ์‹คํ–‰ ๊ณ„ํš์—์„œ ๋ฌด์—‡์„ ์–ด๋–ป๊ฒŒ ์ฝ์–ด์•ผ ํ•˜๋Š”๊ฐ€?

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์‹คํ–‰ ๊ณ„ํš์„ ์ฝ๋Š” ๋ฐฉ๋ฒ•๊ณผ ์‹ค์ œ ์ฟผ๋ฆฌ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ•ด์„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํžˆ ์š”์•ฝํ•˜์ž๋ฉด, EXPLAIN์—์„œ ํ™•์ธํ•  ์ฃผ์š” ์ปฌ๋Ÿผ์€

  • key ์™€ key_len ์„ ํ†ตํ•ด ์˜๋„๋œ ์ธ๋ฑ์Šค๊ฐ€ ์“ฐ์ด๋Š”์ง€
  • type ์„ ํ†ตํ•ด ์ธ๋ฑ์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ์“ฐ์ด๋Š”์ง€
  • rows ์™€ filtered ๋ฅผ ํ†ตํ•ด ๋ถˆํ•„์š”ํ•œ ํ–‰์„ ๋งŽ์ด ์ฝ์ง€๋Š” ์•Š๋Š”์ง€
  • Extra ์˜ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ฟผ๋ฆฌ์˜ ์ถ”๊ฐ€์ ์ธ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•œ์ง€

EXPLAIN ANALYZE ์˜ Tree ํ˜•ํƒœ์˜ ์‹คํ–‰ ๊ณ„ํš์„ ํ†ตํ•ด ์‹ค์ œ ์ฟผ๋ฆฌ๊ฐ€ ์–ด๋Š ๋ถ€๋ถ„์—์„œ ์„ฑ๋Šฅ์ด ์•ˆ๋‚˜์˜ค๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ์–ธ์ œ ์ธ๋ฑ์Šค๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ฟผ๋ฆฌ๋ฅผ ํŠœ๋‹ํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

  • type ๊ฐ’์ด ALL(ํ…Œ์ด๋ธ” ํ’€ ์Šค์บ”) ์ผ๋•Œ. (index - ์ธ๋ฑ์Šค ํ’€ ์Šค์บ”์ผ ๊ฒฝ์šฐ๋Š” ๊ณ ๋ ค)
  • rows ๊ฐ’์ด ํฌ๊ณ , filtered ๊ฐ’์ด ๋‚ฎ์„ ๋•Œ (๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋งŽ์€ ํ–‰์„ ์Šคํ† ๋ฆฌ์ง€ ์—”์ง„์ด ์ฝ์€ ๊ฒƒ)
  • Extra ๊ฐ’์ด Using temporary; Using filesort; ํ•จ๊ป˜ ๋“ฑ์žฅํ•˜๋ฉด ์ฟผ๋ฆฌ์˜ ๋ถ€ํ•˜๊ฐ€ ๋†’๋‹ค. ๋งŒ์•ฝ, Using filesort ๋งŒ ๋‚˜์˜จ๋‹ค๋ฉด ์‹ค์ œ ์‹คํ–‰ ์‹œ๊ฐ„์„ ๋ณด๊ธฐ.

์ถ”๊ฐ€์ ์œผ๋กœ ์ฟผ๋ฆฌ ํŠœ๋‹์—๋Š” ๋‹ค์–‘ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, Nested Loop Join์ด ๋ฐ˜๋ณต๋˜๋Š” ์ƒํ™ฉ์—์„œ๋Š” Hash Join์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

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

 

๋งˆ์ง€๋ง‰์œผ๋กœ, Extra ์ปฌ๋Ÿผ์€ ๋งค์šฐ ๋‹ค์–‘ํ•œ ๊ฐ’์„ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๊ฐ’์„ ๋ฏธ๋ฆฌ ์™ธ์šฐ๊ธฐ๋ณด๋‹ค๋Š” ์ž์ฃผ ๋“ฑ์žฅํ•˜๋Š” ๊ฐ’๋“ค์„ ์šฐ์„ ์ ์œผ๋กœ ํ•™์Šตํ•˜๊ณ , ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ฐพ์•„์„œ ์ตํžˆ๋Š” ๋ฐฉ์‹์ด ๋” ํšจ์œจ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

 

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

 

์ถœ์ฒ˜

- MySQL (MariaDB) ์ธ๋ฑ์Šค ์ปจ๋””์…˜ ํ‘ธ์‹œ๋‹ค์šด 

- 10.์‹คํ–‰๊ณ„ํš ไธญ Real MySQL 8.0 1๊ถŒ

Line ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ MySQL Workbench์˜ VISUAL EXPLAIN์œผ๋กœ ์ธ๋ฑ์Šค ๋™์ž‘ ํ™•์ธํ•˜๊ธฐ