๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿ”ฌapplication/- Database

์˜คํ”„์…‹ ํŽ˜์ด์ง•, ๋‹จ๊ณ„๋ณ„๋กœ ์ตœ์ ํ™”ํ•˜๊ธฐ

by Wonit 2023. 11. 19.

 

์ด ๊ธ€์€ offset based pagination ์„ ๋นŒ๋ฏธ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋‚ด๋ถ€ ๋™์ž‘๊ณผ ์—ฌ๋Ÿฌ ๊ฐœ๋…๋“ค์„ ์•Œ์•„๋ณด๋Š” ๊ธ€ ์ž…๋‹ˆ๋‹ค.

 

2๊ฐœ์˜ ๊ธ€๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ณ , ๊ฐ๊ฐ์˜ ๊ธ€์—์„œ ์–ป์„ ์ˆ˜ ์žˆ๋Š” insight ๊ฐ€ ๋‹ค๋ฅด๋‹ˆ ํ•จ๊ป˜ ์ฝ์œผ๋ฉด ๋”์šฑ ์œ ์ตํ•ฉ๋‹ˆ๋‹ค.

 

  1. ์˜คํ”„์…‹ ํŽ˜์ด์ง•์ด ๋Š๋ฆฐ ์ง„์งœ ์ด์œ 
  2. ์˜คํ”„์…‹ ํŽ˜์ด์ง•, ๋‹จ๊ณ„๋ณ„๋กœ ์ตœ์ ํ™”ํ•˜๊ธฐ <- ํ˜„์žฌ ๊ธ€

 

์ง€๋‚œ ์‹œ๊ฐ„, ์šฐ๋ฆฌ๋Š” ์˜คํ”„์…‹ ํŽ˜์ด์ง•์ด ๋Š๋ฆฐ ์ง„์งœ ์ด์œ  ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜๋‹ค.

 

offset based pagination ์„ ๋ณด๊ณ  ๋ˆ„๊ตฐ๊ฐ€๋Š” ์ด๋Ÿฐ ์ด์•ผ๊ธฐ๋ฅผ ํ•œ๋‹ค.

 

"๊ผญ offset based paging ์„ ํ•ด์•ผํ•˜๋‚˜์š”? cursor based paging ์„ ํ•˜๋ฉด ์•ˆ๋ผ์š”?"

 

๋งž๋Š” ๋ง์ด๋‹ค. ํŽ˜์ด์Šค๋ถ์—์„œ๋„ ๊ฐ€๋Šฅํ•œ ํ•ญ์ƒ cursor based pagination ์ด ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ•์กฐํ•œ๋‹ค.

 

 

ํ•˜์ง€๋งŒ ์–ด๋– ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์—์„œ๋Š” ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

 

offset based paging ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๊ฒƒ์ด ์ข‹์œผ๋‚˜ ํ•ญ์ƒ ๊ทธ๋Ÿด์ˆ˜ ์—†๋‹ค.

 

์–ด๋–ค ์ƒํ™ฉ์—์„œ๋Š” no offset ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ์ˆ˜ ์žˆ๋‹ค

 

  • ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์ด no offset ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ
  • WHERE ์กฐ๊ฑด์ด ์ค‘๋ณต๋˜์–ด cursor ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ

 

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” offset based pagaing ์„ ์ž˜ ์“ฐ๋Š” ๋ฒ•๋„ ์•Œ์•„์•ผํ•˜๋Š”๋ฐ, ์ด์— ๋Œ€ํ•ด์„œ ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๊ฐœ๋…๋“ค๊ณผ ํ•จ๊ป˜ ์ดํ•ดํ•ด๋ณด๋„๋ก ํ•˜์ž

 

์ด๋ฒˆ ๊ธ€์„ ํ†ตํ•ด ์—ฌ๋Ÿฌ๋ถ„๋“ค์€ ์•„๋ž˜ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๊ฐˆ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

 

  • deferred join
  • composite index, concaternate index
  • using filesort vs using index sort
  • covering index

 

TL;DR

์ด๋ฒˆ ๊ธ€์˜ ํ•ต์‹ฌ์„ ์š”์•ฝํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • offset based pagination ์ตœ์ ํ™”
    • deferred join: buffering ๋ฐฉ์‹์˜ ์–ด์ฉ” ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ ๋ฒ„๋ ค์ง(discard)์„ ์ตœ์†Œํ™”ํ•˜์ž
    • covering index: ๋ถˆํ•„์š”ํ•œ Disk I/O ๋ฅผ ์ค„์ด์ž
    • composite index: filesort ๋ฅผ index sort ๋กœ ๋ฐ”๊พธ์ž

offset based pagination ์ตœ์ ํ™” ํ•˜๊ธฐ

 

์ตœ์ ํ™”์— ์•ž์„œ, ์ง€๋‚œ ์‹œ๊ฐ„ offset based pagination ์ด ๋Š๋ฆฐ ์ด์œ ์— ๋Œ€ํ•ด์„œ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ƒ๊ธฐํ•ด๋ณด์ž

 

  • ๋Š๋ฆฐ ์ด์œ  1. ORDER BY ๊ตฌ๋ฌธ์— ์˜ํ•ด streaming ๋ฐฉ์‹์—์„œ buffering ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ๋จ
    • ๊ทธ์— ๋”ฐ๋ผ LIMIT ์ฟผ๋ฆฌ๊ฐ€ ์กด์žฌํ•˜๋”๋ผ๋„ ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๊ฒŒ ๋จ
  • ๋Š๋ฆฐ ์ด์œ  2. ์ •๋ ฌ์„ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด offset ๋งŒํผ Disk I/O ๊ฐ€ ๋ฐœ์ƒ
    • ํŠน์ • ์ผ€์ด์Šค์—์„œ ์œ„์˜ I/O ๋Š” index ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋น„์‹ผ Random I/O ์œ ๋ฐœ
  • ๋Š๋ฆฐ ์ด์œ  3. filesort ๊ฐ€ ์‚ฌ์šฉ๋จ
    • ์ •๋ ฌ์„ ์œ„ํ•œ sort buffer ํ• ๋‹น
    • ๋ฐ์ดํ„ฐ๋“ค์„ ํŠน์ • ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„๊ณ  ์ •๋ ฌ์„ ์ˆ˜ํ–‰ ํ›„ ๊ฒฐ๊ณผ๋ฅผ ๋””์Šคํฌ์— ์ž„์‹œ ์ €์žฅ
    • ์ •๋ ฌ๋œ ์ž„์‹œ ํŒŒ์ผ๋“ค์„ ๋ณ‘ํ•ฉ(mutiple merge) ํ•˜์—ฌ ๊ฒฐ๊ณผ ํ…Œ์ด๋ธ” ์ƒ์„ฑ

 

์ € ์ด์œ ๋“ค ์ค‘ 1๋ฒˆ์€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„์ผ ๊ฒƒ์ด๋‹ค.

 

๊ทธ ์•„๋ž˜์˜ 2๊ฐ€์ง€ ๋Š๋ฆฐ ์ด์œ ๋ฅผ ํ•˜๋‚˜์”ฉ ์ œ๊ฑฐํ•˜๋ฉด์„œ ์„ฑ๋Šฅ์„ ๋Œ์–ด์˜ฌ๋ ค๋ณด์ž

 

์ตœ์ ํ™” 1๋‹จ๊ณ„. deferred join ์„ ์ด์šฉํ•˜๋ผ

 

์ฒซ๋ฒˆ์งธ๋กœ ์ ์šฉํ•  ์ตœ์ ํ™”๋Š” ๋ฐ”๋กœ deferred join ์ด๋ผ๋Š” ๊ธฐ๋ฒ•์ด๋‹ค

 

 

deferred ๋ผ๋Š” ๋œป์€ postponed, delay ์œผ๋กœ ์ง€์—ฐ์‹œํ‚ค๋‹ค๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

 

deferred join ์€ ์ผ์ข…์˜ lazy loading ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

ํ•ต์‹ฌ์€ OFFSET ๊ตฌ๋ฌธ์œผ๋กœ ์ธํ•ด ๊ทธ ๋งŒํผ Disk ์˜ I/O ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์€ ๋ง‰์„ ์ˆ˜ ์—†์ง€๋งŒ, ๋Œ€์‹  ๋ฒ„๋ ค์ง€๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์ด๋‹ค.

 

๋ฒ„๋ ค์ง€๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ค„์—ฌ์„œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ (buffer pool) ์ฒ˜๋ฆฌ๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์ด๋‹ค

 

์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

 

  • ์ •๋ ฌ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” OFFSET ๊ตฌ๋ฌธ์„ sub query ๋กœ ๋งŒ๋“ ๋‹ค.
  • ์•ž์„  ๊ฒฐ๊ณผ๋กœ ์กฐํšŒ๋œ id ๋ฅผ ์›๋ž˜ ํ…Œ์ด๋ธ”๊ณผ join ํ•œ๋‹ค.

 

์ด ๊ณผ์ •์„ ๊ฑฐ์น˜๋ฉด, ๋‹ค๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” OFFSET ์ฟผ๋ฆฌ์—์„œ id ๋งŒ ์กฐํšŒํ•˜๊ฒŒ ๋˜๊ณ , ์›๋ž˜ ํ…Œ์ด๋ธ”๊ณผ join ์„ ํ•˜์—ฌ ์ „์ฒด ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 

deferred join - ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

 

SELECT *
FROM ํ…Œ์ด๋ธ”๋ช…
ORDER BY ์ •๋ ฌ_์กฐ๊ฑด
LIMIT ์˜คํ”„์…‹_๊ฐ’, ํŽ˜์ด์ง€_์‚ฌ์ด์ฆˆ;

SELECT *
FROM ํ…Œ์ด๋ธ”๋ช…
         JOIN (/*์•ž์„  ์˜คํ”„์…‹ ์ฟผ๋ฆฌ ๋‹จ, id ๋งŒ ์กฐํšŒํ•œ๋‹ค*/) AS temp USING (id)
ORDER BY ์ •๋ ฌ_์กฐ๊ฑด;

 

์ฒซ๋ฒˆ์งธ ์ฟผ๋ฆฌ์—์„œ SELECT * FROM.. ์ด ์•„๋‹ˆ๋ผ SELECT id FROM.. ์œผ๋กœ ์ˆ˜์ •ํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋‘๋ฒˆ์งธ ์ฟผ๋ฆฌ์˜ JOIN ์˜ sub query ๋กœ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.

 

๊ทธ๋Ÿผ OFFSET LIMIT ์ด ์ ์šฉ๋  ๋•Œ id ๋งŒ ์กฐํšŒํ•  ๊ฒƒ์ด๊ณ , OFFSET ์ดํ›„ ๋ฒ„๋ ค์ง€๋Š” ๋ฐ์ดํ„ฐ๋“ค๋„ id ๋งŒ ๋ฒ„๋ ค์ง€๊ฒŒ ๋œ๋‹ค.

 

๋งˆ์ง€๋ง‰์œผ๋กœ ์‹ค์ œ client ์—๊ฒŒ ๋ฐ˜ํ™˜ํ•ด์•ผํ•˜๋Š” ๋ฐ์ดํ„ฐ๋“ค์€ JOIN ์™ธ๋ถ€ ์ฟผ๋ฆฌ์—์„œ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค

 

์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณด์ž

 

deferred join - ์˜ˆ์‹œ

 

์•„๋ž˜์˜ ์ฟผ๋ฆฌ๋Š” 170๋งŒ๊ฑด์˜ ๋ฐ์ดํ„ฐ์— ์ ์šฉ๋œ ์ผ๋ฐ˜์ ์ธ OFFSET ์ฟผ๋ฆฌ์ด๋‹ค.

 

SELECT *
FROM simple_todos AS todos
ORDER BY todos.createdAt,
         todos.title
LIMIT 1700000, 10;

 

์ด ์ฟผ๋ฆฌ์—์„œ SELECT ๋’ค์— ๋‚˜์˜ค๋Š” * ๋•Œ๋ฌธ์— OFFSET ๋งŒํผ ๊ฐ€์ ธ์™€ ์ •๋ ฌ์„ ํ•˜๋Š”๋ฐ, ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๋งŽ์ด ์žก์•„๋จน๊ฒŒ ๋œ๋‹ค.

 

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์— deferred join ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด

 

SELECT *
FROM simple_todos AS todos
    JOIN ( -- deferred join ์‹œ์ž‘

      SELECT id -- id ๋งŒ ์กฐํšŒ
      FROM simple_todos
      ORDER BY todos.createdAt, todos.title
      LIMIT 1700000, 10

    ) AS temp USING (id) -- sub query ์˜ ๊ฒฐ๊ณผ๋ฅผ driving table id ๋กœ join
ORDER BY todos.createdAt, todos.title; -- ์žฌ์ •๋ ฌ

 

๊ณผ ๊ฐ™์ด๋  ์ˆ˜ ์žˆ๋‹ค

 

deferred join - ์„ฑ๋Šฅ ๋น„๊ต

 

deferred join ์„ ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ์™€ ๊ทธ๋ ‡์ง€ ์•Š์€ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ ์•ฝ 1.6๋ฐฐ์˜ ์„ฑ๋Šฅ ์ฐจ์ด๋ฅผ ๋ณด์˜€๋‹ค.

์œ ์˜๋ฏธํ•œ ์„ฑ๋Šฅ์˜ ์ฐจ์ด๋Š” ํ™•์ธํ–ˆ์ง€๋งŒ ์•„์ง ๋ถ€์กฑํ•˜๋‹ค.

 

์ด ์ฟผ๋ฆฌ๋Š” 170๋งŒ ๊ฑด์˜ ๋ฐ์ดํ„ฐ์ผ ๋•Œ ์˜๋ฏธ๊ฐ€ ์žˆ์ง€ 10๋งŒ๊ฑด์˜ ์ •๋„์˜ ๋ฐ์ดํ„ฐ์—์„œ๋Š” ํฐ ์ฐจ์ด๊ฐ€ ์—†์„ ๊ฒƒ์ด๋‹ค.

 

๊ทธ๋ƒฅ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋กœ๋งŒ ๋ณด์ผ ๋ฟ์ด๋‹ค.

 

๋” ๋†’์€ ์ˆ˜์ค€์˜ ์ตœ์ ํ™”๋ฅผ ํ•ด๋ณด์ž

์ตœ์ ํ™” 2๋‹จ๊ณ„. Random Disk I/O ๋ฅผ ์ค„์—ฌ๋ณด์ž

 

์‚ฌ์‹ค ์œ„์˜ ๋ฌธ์ œ์ค‘ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ, ์ฆ‰ ๊ฐ€์žฅ ๋Š๋ฆฐ ์ž‘์—…์€ ๋‹น์—ฐํžˆ ๋ฐ์ดํ„ฐ ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” Disk I/O (Random I/O) ์ผ ๊ฒƒ์ด๋‹ค.

์–ด๋–ป๊ฒŒ ํ•˜๋ฉด Disk I/O ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์„๊นŒ?

 

๋‹ต์€ ๊ฐ„๋‹จํ•˜๋‹ค. ๋ฐ์ดํ„ฐ ๋ ˆ์ฝ”๋“œ๋ฅผ ์œ„ํ•œ Disk I/O ๋ฅผ ํ•˜์ง€ ์•Š๋„๋ก ์œ ๋„ํ•˜๋ฉด ๋œ๋‹ค

 

DB ์˜ ์‹คํ–‰ ์—”์ง„์ด ๋ฐ์ดํ„ฐ ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด Disk I/O ๋ฅผ ํ•˜๊ธฐ ์ „์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์ฅ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

 

  • ORDER BY ์กฐ๊ฑด์— createdAt ์ด ์žˆ์–ด์„œ ์–ด์ฉ” ์ˆ˜ ์—†์ด Disk ์— ์ ‘๊ทผํ•ด์•ผํ•œ๋‹ค?
    • ๊ทธ๋Ÿผ index ๋ฅผ ๊ฑธ์–ด๋ฒ„๋ฆฌ์ž.
    • index ๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋†“์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ ˆ์ฝ”๋“œ ์ „์ฒด๋ฅผ ์กฐํšŒํ•˜๋Š” Disk I/O ๊ฐ€ ์‚ฌ๋ผ์งˆ ๊ฒƒ์ด๋‹ค
  • SELECT * FROM.. ๋•Œ๋ฌธ์— ์ „์ฒด ๋ฐ์ดํ„ฐ ์กฐํšŒ๋ฅผ ์œ„ํ•ด Disk ์— ์ ‘๊ทผํ•ด์•ผํ•œ๋‹ค?
    • ๊ทธ๋Ÿผ SELECT id FROM.. ์œผ๋กœ pk(id) ๋งŒ ์กฐํšŒํ•˜๋„๋ก ํ•˜์ž
    • pk(id) ๋Š” ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” index ์ด๊ธฐ ๋•Œ๋ฌธ์— index ์กฐํšŒ์‹œ ๋ชจ๋“  ์กฐ๊ฑด์ด ์ถฉ์กฑ๋œ๋‹ค.
    • ๋ฐ์ดํ„ฐ ๋ ˆ์ฝ”๋“œ ์ ‘๊ทผ์„ ์œ„ํ•œ Disk IO ๊ฐ€ ์—†์–ด์งˆ ๊ฒƒ์ด๋‹ค

 

์‚ฌ์‹ค ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์ด ๋ฐ”๋กœ Covering Index ์ด๋‹ค.

 

Disk I/O ์ค„์ด๊ธฐ - covering index

 

covering index ๋Š” ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” index ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

 

SELECT username
FROM users
WHERE username = '์žฅ์›์ต'

ALTER TABLE users
    ADD INDEX idx_name (username);

 

์œ„์™€ ๊ฐ™์ด index ๋ฅผ ๊ฑธ๊ณ  index ์— ์„ค์ •๋œ column name ์œผ๋กœ WHERE ์กฐ๊ฑด๊ณผ SELECT ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค๋ฉด Table Scan ์ด ์•„๋‹ˆ๋ผ Index Scan ์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค

๊ทธ๋Ÿผ ๊ฒฐ๊ตญ ํŠน์ • ๋ฐ์ดํ„ฐ ์กฐํšŒ๋ฅผ ์œ„ํ•ด ๋ฐ์ดํ„ฐ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์กฐํšŒํ•˜๋Š” Disk I/O ๊ฐ€ ์‚ฌ๋ผ์งˆ ๊ฒƒ์ด๋‹ค.

 

์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค๋ฅผ ์ ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ๋น„๊ตํ•˜๊ธฐ ์ „์— ์•„๋ž˜ ์ตœ์ ํ™”๋ฅผ ๋จผ์ € ํ™•์ธํ•ด๋ณด์ž.

 

์ตœ์ ํ™” 3 ๋‹จ๊ณ„. filesort ๋ฅผ ์—†์• ์ž

 

filesort ๋„ ์—ญ์‹œ ๋ณต์žกํ•˜๊ณ  ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์ค‘ ํ•˜๋‚˜๋กœ ๊ผฝํžŒ๋‹ค.

 

filesort ๋ฅผ ์—†์• ๋ฉด ์„ฑ๋Šฅ ํ–ฅ์ƒ์ด ์ž๋ช…ํ•˜๋‹ค!!

 

filesort ๋ฅผ ์—†์• ๊ธฐ - ์‚ฌ์ „์ง€์‹

 

filesort ๋ฅผ ์—†์• ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ์„  ๊ทธ๊ฒŒ ๋ฌด์—‡์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  ๋Œ€์•ˆ์€ ๋ฌด์—‡์ธ์ง€ ์•Œ์•„์•ผ ํ•œ๋‹ค.

 

filesort ์™€ index sort ์— ๋Œ€ํ•œ ์„ค๋ช…์€ ์ง€๋‚œ ์˜คํ”„์…‹ ํŽ˜์ด์ง•์ด ๋Š๋ฆฐ ์ง„์งœ ์ด์œ  ์—์„œ ์–ธ๊ธ‰ํ•˜์˜€์ง€๋งŒ ๊ฐ„๋žตํžˆ ์ •๋ฆฌํ•˜์ž๋ฉด

 

  • index sort
    • ํ•ญ์ƒ ์ •๋ ฌ๋œ ์ƒํƒœ๋กœ ์ €์žฅํ•˜๋Š” index ์˜ ํŠน์„ฑ์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ
    • ORDER BY ๊ตฌ๋ฌธ์— index ๋กœ ์ง€์ •๋œ column ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฏธ๋ฆฌ ์ •๋ ฌ๋œ ์ธ๋ฑ์Šค์˜ ํŠน์„ฑ์„ ์ด์šฉํ•ด์„œ ์ •๋ ฌ๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜
    • ์ •๋ ฌ์„ ์œ„ํ•œ ์ž„์‹œ file ์ƒ์„ฑ ๋ฐ multiple merge ๋ฅผ ์œ„ํ•œ ์ถ”๊ฐ€์ ์ธ ์ž‘์—… ์—†์Œ
    • ์ •๋ ฌ ์ž‘์—…์ค‘ ๊ฐ€์žฅ ๋น ๋ฅธ ์†๋„ ๋ณด์žฅ
  • filesort
    • filesort ๋Š” ์ •๋ ฌ์„ ์œ„ํ•ด ๋””์Šคํฌ๋‚˜ ์ž„์‹œ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
    • ์ฃผ๋กœ index sort ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉ๋˜๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์„ ํ•œ๋‹ค
    • ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒ˜๋ฆฌ๋˜๋ฏ€๋กœ ๋น„๊ต์  ๋Š๋ฆผ
      • ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— sort buffer ๋ฅผ ์ƒ์„ฑ(ํ• ๋‹น๋ฐ›์Œ)
        • sort buffer ์—์„œ ์ •๋ ฌ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰
      • ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๋ธ”๋ก ๋‹จ์œ„๋กœ ๋‚˜๋ˆ”
        • ๋ธ”๋ก ๋‚ด์˜ ์ •๋ ฌ ๊ฒฐ๊ณผ๋ฅผ file ํ˜•ํƒœ๋กœ ์ž„์‹œ ์ €์žฅ
        • ์ถ”๊ฐ€์ ์ธ Disk I/O ๋ฐœ์ƒ
      • ์ •๋ ฌ๋œ ๊ฒฐ๊ณผ๋“ค์„ ๋ณ‘ํ•ฉํ›„ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
        • multi-merge ์ž‘์—… ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ฒฐ๊ณผ ํ…Œ์ด๋ธ” ์ƒ์„ฑ

 

filesort ๋ฅผ ์—†์• ๊ธฐ - ๋ณตํ•ฉ ์ธ๋ฑ์Šค ์„ค์ •

 

filesort ๋ฅผ ์—†์• ๊ณ  ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ index sort ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์œ ๋„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ORDER BY ์— ๋“ค์–ด๊ฐ€๋Š” ์กฐ๊ฑด์ด ๋ชจ๋‘ index ๋กœ ์ง€์ •๋œ column ์ด์–ด์•ผ ํ•œ๋‹ค.

 

ORDER BY ์— ๋“ค์–ด๊ฐ€๋Š” ์กฐ๊ฑด์„ index ๋กœ ํ•˜๋Š” ๋ณตํ•ฉ ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋œ๋‹ค

 

select createdAt, content
from simple_todos as todos
order by createdAt, title
LIMIT 1700000, 10;

ALTER TABLE simple_todos
    ADD INDEX idx_createdAt_title (createdAt, title);

 

๊ทธ๋Ÿผ ์ •๋ ฌ ๊ณผ์ •์—์„œ sort buffer ๋‚˜ temp file io ๋ฅผ ํ†ตํ•œ ์ •๋ ฌ์ด ์‚ฌ๋ผ์ง€๊ณ  ์ด๋ฏธ ์ •๋ ฌ๋œ index ์ˆœ์„œ๋Œ€๋กœ ๋ฐ˜ํ™˜์„ ํ•˜๊ฒŒ๋  ๊ฒƒ์ด๋‹ค.

 

๋ณตํ•ฉ ์ธ๋ฑ์Šค ๋ฐ covering index ์ ์šฉ ํ›„ ์„ฑ๋Šฅ ๋น„๊ต

 

170๋งŒ๊ฑด์˜ ๋ฐ์ดํ„ฐ๋ฅผ Ordering ํ•˜์˜€์„ ๋•Œ์˜ ์„ฑ๋Šฅ ์ฐจ์ด๋ฅผ ๋ด๋ณด์ž

 

์•ž์€ order by ์— ํ•ด๋‹นํ•˜๋Š” ์ •๋ ฌ ์กฐ๊ฑด์— ๋ณตํ•ฉ ์ธ๋ฑ์Šค๋ฅผ ๊ฑธ๊ธฐ ์ „์ด๊ณ  ๋’ค๋Š” index ๋ฅผ ์ถ”๊ฐ€ํ•œ ํ›„๋‹ค.

 

7,585ms ์—์„œ 234ms ๋กœ ์•ฝ 32๋ฐฐ์˜ ์†๋„ ์ฐจ์ด๊ฐ€ ๋‚œ๋‹ค

๋งˆ์ง€๋ง‰! ์ด ๋ชจ๋“  ์ตœ์ ํ™”๋ฅผ ๋‹ค ์ ์šฉํ•ด๋ณด์ž

์ตœ์ ํ™” ์ „ ์ฟผ๋ฆฌ

์•„๋ž˜์˜ ์ฟผ๋ฆฌ๋Š” ์ตœ์ ํ™”๋ฅผ ํ•˜๊ธฐ ์ „์˜ ์ฟผ๋ฆฌ๋‹ค.

select *
from simple_todos as todos
order by createdAt, title
LIMIT 1700000, 10;

์ตœ์ ํ™” ํ›„ ์ฟผ๋ฆฌ

์ตœ์ ํ™”๋ฅผ ๋งˆ์นœ ์ฟผ๋ฆฌ์ด๋‹ค.

SELECT *
FROM simple_todos AS todos
         JOIN (SELECT id
               FROM simple_todos
               ORDER BY createdAt,
                        title
               LIMIT 1700000, 10) AS temp USING (id)
ORDER BY todos.createdAt, todos.title;

ALTER TABLE simple_todos
    ADD INDEX idx_createdAt_title (createdAt, title);

 

์šฐ๋ฆฌ๋Š” ์ด ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๊ฝค๋‚˜ ๋งŽ์€ ๊ฒƒ์„ ์ ์šฉํ•˜์˜€๋‹ค.

 

  • buffering ๋ฐฉ์‹์˜ ์–ด์ฉ” ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ ๋ฒ„๋ ค์ง(discard) ๋ฅผ ์œ„ํ•ด deferred join ์„ ์ ์šฉํ–ˆ๋‹ค.
  • ๋ถˆํ•„์š”ํ•œ Disk I/O ๋ฅผ ์—†์• ๊ธฐ ์œ„ํ•ด covering index ๋ฅผ ์ ์šฉํ•˜์˜€๋‹ค
  • filesort ๋ฅผ index sort ๋กœ ๋ฐ”๊พธ๊ธฐ ์œ„ํ•ด ์ •๋ ฌ ์กฐ๊ฑด์— composite index ๋ฅผ ์ ์šฉํ•˜์˜€๋‹ค

 

๊ทธ ๊ฒฐ๊ณผ ๊ธฐ์กด ๋Œ€๋น„ ์•ฝ 62๋ฐฐ ๋นจ๋ผ์ง„ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค

 

 

์ด ์†๋„๋Š” ์•„๋งˆ ๋ฐ์ดํ„ฐ ์–‘์ด ๋งŽ์•„์งˆ ์ˆ˜๋ก, ํŽ˜์ด์ง€๊ฐ€ ๊นŠ์–ด์งˆ์ˆ˜๋ก ๋” ๋Š˜์–ด๋‚  ๊ฒƒ์ด๋‹ค.

๊ฒฐ๋ก 

 

์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์žฅ์น˜๋ฅผ ํ•ด๋‘์—ˆ์ง€๋งŒ ๊ฒฐ๊ตญ ๊ฒ€์ƒ‰ ์กฐ๊ฑด, ์ •๋ ฌ ์กฐ๊ฑด๋งˆ๋‹ค ์ธ๋ฑ์Šค๋ฅผ ๊ฑฐ๋Š”๊ฒƒ์€ ์‚ฌ์‹ค์ƒ ๋งค์šฐ ์–ด๋ ต๋‹ค.

 

๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๋Š” ์ € ์ตœ์ ํ™” ์ฟผ๋ฆฌ๊ฐ€ ์ด๋Ÿฌํ•œ ์ง€์‹์ด ์—†์ด ๋ณธ๋‹ค๋ฉด ๋งค์šฐ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋กœ ๋ณด์ผ ๊ฒƒ์ด๋‹ค.

 

์–ด์ฉ” ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด cursor ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง•์œผ๋กœ ๊ฐ€๋Š” ๊ฒƒ๋„ ์ข‹์€ ์„ ํƒ์ด๋‹ค.

 

์ด๋ ‡๊ฒŒ ์•ž์„  ๊ธ€๊ณผ ์ด๋ฒˆ ๊ธ€์„ ํ†ตํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ‚ค์›Œ๋“œ์™€ ๊ธฐ์ˆ ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜๋‹ค.

 

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

๋Œ“๊ธ€