๐Ÿ“ƒ

Offset & Cursor

๋‹ด๋‹น์ž๋“ค
์นดํ…Œ๊ณ ๋ฆฌ
Skill
์ฃผ์ œ
ํŽ˜์ด์ง•
๋‚˜์˜ ๋ธ”๋กœ๊ทธ
์™„๋ฃŒ์œจ%
ํ”„๋กœ์ ํŠธ
์ธ์Šคํƒ€๋€จ๋žจ
์ƒํƒœ
์™„๋ฃŒ

What

  • ํŽ˜์ด์ง•์ด๋ž€?
โœ๐Ÿป
ํŽ˜์ด์ง•์€ ์ฑ… ํŽ˜์ด์ง€์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌถ์Œ์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ณผ์ •
  • ์ข…๋ฅ˜
    • ์˜คํ”„์…‹ ํŽ˜์ด์ง•
      • OffSet : ์–ด๋”” ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ๊ฐ€์ ธ์˜ฌ๊ฒƒ์ธ์ง€?
      • Limit : ๋ช‡๊ฐœ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๊ฒƒ์ธ์ง€?
      • SELECT * FROM ${table_name} ORDER BY ${Column} OFFSET 10 LIMIT 5
      • ๋ณดํ†ต offset ํŽ˜์ด์ง•์€ ํ”„๋ก ํŠธ ์—”๋“œ์—์„œ ์ด๋ ‡๊ฒŒ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.
      • ํŽ˜์ด์ง€ ๋ฒ„ํŠผ๊ณผ ํ•จ๊ผ ์“ฐ์ด๋ฉฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•จ์œผ๋กœ์จ ํŽ˜์ด์ง€๋ฅผ ํœ™ํœ™ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      notion image
  • ์ปค์„œ ํŽ˜์ด์ง•
    • Cursor - ์‚ฌ์ „์ ์˜๋ฏธ
    • ์‚ฌ์ „์  ์˜๋ฏธ : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค์„œ๋Š” ์ผ๋ จ์˜ ๋ฐ์ดํ„ฐ์— ์ˆœ์ฐจ์ ์œผ๋กœ ์•ก์„ธ์Šคํ•  ๋•Œ ๊ฒ€์ƒ‰ ๋ฐ "ํ˜„์žฌ ์œ„์น˜"๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฐ์ดํ„ฐ ์š”์†Œ DB ์˜๋ฏธ : ํŠน์ • SQL ๋ฌธ์žฅ์„ ์ฒ˜๋ฆฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ์˜์—ญ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ผ์ข…์˜ ํฌ์ธํ„ฐ ์ž…๋‹ˆ๋‹ค.
       
    • ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ์™€ ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ(ํŽ˜์ด์Šค๋ถ, ์Šฌ๋ž™ , ํŠธ์œ„ํ„ฐ ๋“ฑ)์„ ๋‹ค๋ฃจ๋Š” ์›น์‚ฌ์ดํŠธ์—์„œ ์“ฐ์ด๋Š” ํŽ˜์ด์ง• ๋ฐฉ๋ฒ•์œผ๋กœ์จ, ํ”„๋ก ํŠธ์—์„œ ๋ฌดํ•œ ์Šคํฌ๋กค(์ธ์Šคํƒ€ ๊ทธ๋žจ, ํŽ˜์ด์Šค๋ถ์ฒ˜๋Ÿผ ํ•˜๋‹จ์œผ๋กœ ๊ณ„์† ์Šคํฌ๋กค ๋˜๋Š” ํŽ˜์ด์ง• ๋ฐฉ์‹)์„ ์ง€์›
    •  
      notion image

Why [์™œ cursor ์ธ๊ฐ€?]

โœ๐Ÿป
์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๋‹ค๋ฃฐ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ปค์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ •์ ์œผ๋กœ ์œ ์ง€ํ•  ๊ฒƒ์„ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๊ฐ€ ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ์ œ๊ฑฐ๋  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ, ๊ทธ ๋ฐ์ดํ„ฐ๋“ค์€ ์ •์ƒ์ ์œผ๋กœ ์กฐํšŒ๋  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
 

์šฐ์ˆ˜ํ•œ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ

โœ๐Ÿป
์˜คํ”„์…‹์€ ๋‹จ์ˆœํžˆ ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒํ•˜๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๊ฑด๋„ˆ ๋›ฐ๋Š” ๋ ˆ์ฝ”๋“œ์˜ ์ˆ˜๋‹ค.
์ฆ‰, ์š”์ฒญํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”๋กœ ์กฐํšŒํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์ด์ „์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์กฐํšŒํ•˜๊ณ  ๊ทธ ResultSet์—์„œ ์˜คํ”„์…‹์„ ์กฐ๊ฑด์œผ๋กœ ์ž˜๋ผ๋‚ด๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
  • ์˜คํ”„์…‹ ์ฟผ๋ฆฌ ์˜ˆ์‹œ
SELECT * FROM ( SELECT ROWNUM() over (ORDER BY timestamp) rnum , A.* FROM table A ORDER BY timestamp ) WHERE ROWNUM BETWEEN 6 AND 10
  • timestamp๋ฅผ ์ •๋ ฌ ๊ธฐ์ค€์œผ๋กœ ์ „์ฒด ๋ฐ์ดํ„ฐ์˜ ํ–‰๋ฒˆํ˜ธ๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์ด ๋ฒˆํ˜ธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ž˜๋ผ๋‚ด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ์ด๊ฑด ์˜คํ”„์…‹ ์ˆซ์ž๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ํฐ ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๋ถ€๋ถ„์—์„œ ์•„์ฃผ ํฐ ์ฐจ์ด๋ฅผ ๋ณด์ž…๋‹ˆ๋‹ค.
    • notion image

      ๋˜ ๊ณ ๋ คํ•ด๋ด์•ผ ํ•  ๊ฒƒ๋“ค

      โœ๐Ÿป
      ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€๋ฅผ ์ด์šฉํ•  ํ™•๋ฅ ์€ ์–ผ๋งˆ์ •๋„ ๋ ๊นŒ? 0%๋Š” ์•„๋‹ˆ๊ฒ ์ง€๋งŒ, ๋งค์šฐ ์ž‘์„ ๊ฒƒ์ด๋‹ค.
      ๊ทธ๋ ‡์ง€๋งŒ ๊ตณ์ด 7๋ฐฑ๋งŒ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹ˆ๋”๋ผ๋„, ๊ทธ๋ž˜ํ”„์—์„œ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ์˜คํ”„์…‹ ํŽ˜์ด์ง•์˜ ์‹œ๊ฐ„๋ณต์žก์„ฑ O(N), O(offset+limit) ๋•Œ๋ฌธ์— ์˜คํ”„์…‹์ด ์ปค์งˆ์ˆ˜๋ก ์‹œ๊ฐ„์ด ์ฆ๊ฐ€ํ•ด UX๋Š” ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด ์ปค์„œ ํŽ˜์ด์ง•์˜ ๊ฒฝ์šฐ๋Š” O(1), O(limit)๋กœ ํ•ญ์ƒ ์ผ์ •ํ•ฉ๋‹ˆ๋‹ค.
      ๋”ฐ๋ผ์„œ ์ „๋ณด๋‹ค ํŽ˜์ด์ง€ ๋กœ๋”ฉ์ด ๋А๋ ค์ง„ ๊ฒƒ๊ฐ™์€ ๋А๋‚Œ์ด ๋“ ์ ์ด ์žˆ๋‹ค๋ฉด, ์•„๋งˆ๋„ ๊ทธ๊ฑด ์˜คํ”„์…‹ ํŽ˜์ด์ง•์˜ ๋น„ํšจ์œจ์„ฑ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค โ€ผ๏ธ

๋ˆ„๋ฝ๋˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ - ์‚ฌ์šฉ์ž์˜ ๊ธฐ๋Œ€ ๋ถ€์‘

  • Offset ํŽ˜์ด์ง• ์˜ˆ์‹œ - sns์—์„œ ์ตœ๊ทผ ํ”ผ๋“œ 3๊ฐœ์˜ ํ”ผ๋“œ๊ฐ€ ์˜ฌ๋ผ์™”๋‹ค.
    • ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€๋‹น ๋ฐ์ดํ„ฐ ๊ตฌ์„ฑ ==== 1 ํŽ˜์ด์ง€ ======= A B F ==== 2 ํŽ˜์ด์ง€ ====== G H I ==== 3 ํŽ˜์ด์ง€ ====== . . . sns์—์„œ ์ตœ๊ทผ ํ”ผ๋“œ 3๊ฐœ์˜ ํ”ผ๋“œ๊ฐ€ ์˜ฌ๋ผ์™”๋‹ค. ==== 1 ํŽ˜์ด์ง€ ======= A B C [new] ==== 2 ํŽ˜์ด์ง€ ====== D [new] E [new] F ==== 3 ํŽ˜์ด์ง€ ====== G H I
  • ํ•ด๋‹น ๋ฐ์ดํ„ฐ์˜ ์ƒˆ๋กœ์šด ์‚ฝ์ž… ์œผ๋กœ ํ˜„์žฌ ๋ณด๊ณ  ์žˆ๋Š” 2ํŽ˜์ด์ง€์—์„œ 3ํŽ˜์ด์ง€๋กœ ๊ฐˆ ๋–„ ๋˜‘๊ฐ™์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณด์ด๊ฒŒ ๋  ์ˆ˜ ์žˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ? ํ•  ์ˆ˜ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์‚ฝ์ž… ์™ธ๋กœ ์‚ญ์ œ๊ฐ€ ์ด๋ฃจ์–ด์งˆ ๊ฒฝ์šฐ๋„ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.
  • ์‹ค์ œ์ ์œผ๋กœ ์‚ฌ์šฉ๋  ์ฟผ๋ฆฌ ์˜ˆ์‹œ
SELECT * FROM table ORDER BY timestamp OFFSET 0 LIMIT 3 SELECT * FROM table ORDER BY timestamp OFFSET 3 LIMIT 3 SELECT * FROM table ORDER BY timestamp OFFSET 6 LIMIT 3 SELECT * FROM table ORDER BY timestamp OFFSET 9 LIMIT 3
 
  • Cursor ํŽ˜์ด์ง• ์˜ˆ์‹œ - sns์—์„œ ์ตœ๊ทผ ํ”ผ๋“œ 3๊ฐœ์˜ ํ”ผ๋“œ๊ฐ€ ์˜ฌ๋ผ์™”๋‹ค.
์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€๋‹น ๋ฐ์ดํ„ฐ ๊ตฌ์„ฑ ==== 1 ํŽ˜์ด์ง€ ======= A B F ==== 2 ํŽ˜์ด์ง€ ====== G H I ==== 3 ํŽ˜์ด์ง€ ====== . . . sns์—์„œ ์ตœ๊ทผ ํ”ผ๋“œ 3๊ฐœ์˜ ํ”ผ๋“œ๊ฐ€ ์˜ฌ๋ผ์™”๋‹ค. ==== 1 ํŽ˜์ด์ง€ ======= A B F ==== 2 ํŽ˜์ด์ง€ [๋‹ค์Œ ๋ฐ์ดํ„ฐ ์š”์ฒญ ๊ฐ€์ ธ์˜ด] ====== G H I ==== 3 ํŽ˜์ด์ง€[๋‹ค์Œ ๋ฐ์ดํ„ฐ ์š”์ฒญ ๊ฐ€์ ธ์˜ด]====== . . .
  • ์™œ ์‚ฝ์ž…๋œ ๋ฐ์ดํ„ฐ๋“ค์„ ์•ˆ๋ถˆ๋Ÿฌ์˜ฌ๊นŒ?
  • ์˜คํ”„์…‹์€ ๋งค๋ฒˆ ํ•ญ์ƒ ๋ฐ์ดํ„ฐ๋“ค์„ ๋ชจ๋‘ ๊ฐ€์ ธ์™€์„œ ์„ ๋ณ„์„ ํ•˜์ง€๋งŒ, ์ปค์„œ๋Š” ์ง€์ •๋œ ๊ธฐ์ค€ ์ด์™ธ์—๋Š” ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๋’ค์ ๊ฑฐ๋ฆฌ์ง€ ์•Š๊ณ  ํŠน์ • ์กฐ๊ฑด ์ดํ›„์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋“ค๋งŒ ์„ ๋ณ„ํ•ด์„œ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
โ€ผ๏ธ
SELECT * FROM table WHERE cursor > timestamp ORDER BY timestamp LIMIT 5
 

์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์Šค์ฝ”ํ”„

โœ๐Ÿป
์ปค์„œ ํŽ˜์ด์ง•๋„ ๋‹จ์ ์ด ์กด์žฌํ•˜๋ฏ€๋กœ ์ž˜ ๊ณ ๋ คํ•ด์•ผํ•œ๋‹ค.[์‹ ๊ฒฝ์“ธ๊ฒŒ ์—„์ฒญ ๋งŽ๋‹ค.]
์ œํ•œ๋œ ์ •๋ ฌ ๊ธฐ๋Šฅ
  • Firstname๊ณผ Lastname์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•œ ํ…Œ์ด๋ธ” ํ•˜๋‚˜๋ฅผ ๊ฐ€์ • ํ•ด๋ด…๋‹ˆ๋‹ค.
  • ์ด ๊ฒฝ์šฐ๋Š” ์ปค์„œ ํŽ˜์ด์ง•์— ๊ตฌํ˜„์— ๋ฌธ์ œ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ปค์„œ ํŽ˜์ด์ง• ์ •๋ ฌ์˜ ์š”๊ตฌ์‚ฌํ•ญ ์ค‘ ํ•˜๋‚˜๋Š” ์ •๋ ฌํ•  ์ปฌ๋Ÿผ์— ์ค‘๋ณต๋œ ๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ์•ˆ๋˜๊ณ , ์ˆœ์ฐจ์ ์ด์–ด์•ผ ํ•œ๋‹ค ๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ์ปค์„œ ํŽ˜์ด์ง•์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด "์ด ๋ ˆ์ฝ”๋“œ ๋‹ค์Œ ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒํ•ด์ค˜"๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” ํŠน์ • ์ง€์ ์„ ์ปค์„œ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด๋Ÿฐ ์š”๊ตฌ์‚ฌํ•ญ ๋•Œ๋ฌธ์—, ๋Œ€๋ถ€๋ถ„์˜ ์ปค์„œ ํŽ˜์ด์ง•์€ timestamp ์ปฌ๋Ÿผ์„ ๊ธฐ์ค€์œผ๋กœ ํ•œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ž‘์€ ๋‹จ์œ„์˜ timestamp๋Š” ์ˆœ์ฐจ์ ์ด๊ณ  ๊ณ ์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
Firstname์€ ์ˆœ์ฐจ์ ์ผ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ณ ์œ ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊น€, ๋ฐ•, ์ตœ์”จ๋ฅผ ์ ์–ด๋„ 100๋ช…์€ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๊ฒฝ์šฐ ์ปค์„œ๋Š” ๊ณ ์œ ํ•œ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ์ „์ฒด ๋ ˆ์ฝ”๋“œ ์ง‘ํ•ฉ์„ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ปค์„œ๋ฅผ ๊ตฌํ˜„ํ•œ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฑด๋„ˆ ๋›ฐ๊ฑฐ๋‚˜ ์ค‘๋ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํšŒ์› ํ…Œ์ด๋ธ”์˜ ๊ฒฝ์šฐ ์ •๋ ฌ ๊ธฐ์ค€์œผ๋กœ ์ด๋ฉ”์ผ์ด ๋” ์ข‹์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณ ์œ ํ•˜๊ณ  ์ˆœ์ฐจ์  ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์š”๊ตฌ์‚ฌํ•ญ์ด Lastname ๋˜๋Š” Firstname์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด ์ปค์„œ ํŽ˜์ด์ง•์ด ์ ํ•ฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„๊ณผ ์„ฑ์„ ์—ฐ๊ฒฐํ•˜๊ฑฐ๋‚˜ ์—ฌ๋Ÿฌ ์—ด์˜ ํŠœํ”Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ์œ ํ•œ ์—ด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๋กœ ์ธํ•ด ์ปค์„œ ํŽ˜์ด์ง•์ด ์˜คํ”„์…‹ ํŽ˜์ด์ง•๋ณด๋‹ค ํ›จ์”ฌ ๋А๋ ค์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. SQL๋ฌธ์—์„œ ์—ฐ๊ฒฐ ๋ฐ ํŠœํ”Œ ๋น„๊ต๋Š” ๋ชจ๋‘ ์‹œ๊ฐ„๋ณต์žก๋„ O(N), O(์ „์ฒด ๋ฐ์ดํ„ฐ) ๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ์ปค์„œ๋ฅผ ์ž˜๋ชป ์“ฐ๋Š” ๊ฒฝ์šฐ ํฌํฌ๋ชฌ์“ฐ์˜ ์ €ํ•˜
notion image
  • ์‹ค์ œ๋กœ, ์ปค์„œ ํŽ˜์ด์ง•์ด ์˜คํ”„์…‹ ํŽ˜์ด์ง•๋ณด๋‹ค ์ฒซ๋ฒˆ์งธ ํŽ˜์ด์ง€๋ฅผ ํ›จ์”ฌ ๋А๋ฆฌ๊ฒŒ ์กฐํšŒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ง๊ด€์ ์œผ๋กœ ์ดํ•ด๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์ง€๋งŒ Cursor(Concatenated)๊ฐ€ ์šฐํ•˜ํ–ฅ ํ•˜๋Š” ์ด์œ ๋Š” ๋ ˆ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„ ์งˆ์ˆ˜๋ก SELECT ํ•˜๋Š” ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

How

Offset

  • ์Šคํ”„๋ง jpa์— ์ œ๊ณตํ•˜๋Š” Pageable ๊ฐ์ฒด ์‚ฌ์šฉ
    • notion image
  • Pageable ๊ตฌํ˜„์ฒด์—๋Š” PageRequest๋ผ๋Š” ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
    • ํ•ด๋‹น PageRequest๋Š” ํ•ด๋‹น ํŽ˜์ด์ง•์— ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒƒ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๋ช‡๊ฐœ์”ฉ ๋ณด์—ฌ์ค„ ๊ฒƒ์ธ์ง€(limit) ์–ด๋”” ํŽ˜์ด์ง€(offset์€ ์•„๋‹ˆ์ง€๋งŒ ์—ฐ๊ด€์ด ์žˆ์Œ.)๋ฅผ ๋ณผ๊ฒƒ์ธ์ง€?์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
    • ํด๋ผ์ด์–ธํŠธ๋กœ ๋ถ€ํ„ฐ ์‚ฌ์ด์ฆˆ์™€ ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.
    • PageRequest ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • public static PageRequest of(int page, int size, Sort sort) { // ํŽ˜์ด์ง€๋Š” 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค! ์‚ฌ์šฉ์ž๋Š” 1,2,3 ์ด์ง€๋งŒ ์ปดํ“จํ„ฐ ์„ธ๊ณ„๋Š” 0๋ฒˆ์งธ๋ถ€ํ„ฐ ์กด์žฌํ•จ์„ ์ธ์ง€ํ•ด์•ผ ํ•œ๋‹ค. return new PageRequest(page, size, sort); }
Pageable ๊ฐ์ฒด๋Š” ๋งŽ์€ ํŽธ์˜ ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ
  • ์ „ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€ ๋“ฑ๋“ฑโ€ฆ
    • notion image
  • ์ถ”๊ฐ€์ ์œผ๋กœ ์ด๊ฒƒ๋ณด๋‹ค UI์—์„œ๋Š” ํ˜„์žฌ ํŽ˜์ด์ง€๋“ค์˜ ๋ฒˆํ˜ธ๊ฐ€ ํ•„์š”ํ•˜๋‹ˆ ๋”ฐ๋กœ ์ปค์Šคํ…€ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค!
 

Cursor

 
  • ํŽ˜์ด์ง€๋ฅผ ์ฒ˜์Œ ์ง„์ž…ํ–ˆ์„ ๋•Œ๋Š” ๋ณ„๋„์˜ ํŽ˜์ด์ง•์„ ํ•˜์ง€ ์•Š๊ณ  ์ผ์ • ๊ฐœ์ˆ˜๋งŒํผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
    • ์กฐํšŒํ•œ ๋ฐ์ดํ„ฐ ์ค‘ ๋งˆ์ง€๋ง‰ ๋ฐ์ดํ„ฐ์˜ ์ปค์„œ๊ฐ’์„ ์กฐํšŒ ๋ฐ์ดํ„ฐ์™€ ํ•จ๊ป˜ ํ”„๋ก ํŠธ์— ๋„˜๊ฒจ์ค๋‹ˆ๋‹ค.
  • ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ์—๋Š” ๋ฐฑ์—”๋“œ์—๊ฒŒ ์ปค์„œ ๊ฐ’๊ณผ ํ•จ๊ป˜ โ€œ์ด ์ปค์„œ ๊ฐ’ ์ดํ›„์˜ ๋ฐ์ดํ„ฐ๋ฅผ N๊ฐœ ์กฐํšŒ ํ•ด์ฃผ์„ธ์š”" ๋ผ๊ณ  ์š”์ฒญ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • ๋ฐฑ์—”๋“œ๋Š” ์ปค์„œ ๊ฐ’ ์ดํ›„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.(Member๋ฅผ id ์—ญ์ˆœ์œผ๋กœ ์กฐํšŒ, ์ตœ๊ทผ ์ปค์„œ๊ฐ€ id = 10์ผ ๊ฒฝ์šฐ)
    • ex) SELECT m From Member m WHERE id < 10 ORDER BY id DESC LIMIT 6;
 

โ—๏ธ Cursor ๋ฐฉ์‹ ํŽ˜์ด์ง• ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์ 

 
  • ๋ฐ์ดํ„ฐ ์œ ์‹ค์— ์ฃผ์˜ ํ•˜์„ธ์š” โ€ผ๏ธ 
์ค‘๋ณต์ด ๋ฐœ์ƒํ•˜๋Š” ์ปฌ๋Ÿผ์„ ์ปค์„œ๋กœ ์‚ฌ์šฉ ์‹œ ๋ฐ์ดํ„ฐ ์†์‹ค์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
 
notion image
notion image
 
์ฒ˜์Œ id๊ฐ€ 18, 17, 14์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ ์™”๊ณ  ์ปค์„œ ๊ฐ’์€ โ€˜2022-08-14 09:53:39โ€™ ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
์ด์ œ ๋‹ค์Œ ํŽ˜์ด์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๊ฒฝ์šฐ์—๋Š” โ€˜2022-08-14 09:53:39โ€™ ๋ณด๋‹ค ์ „ ์‹œ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๊ฒ๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ id๊ฐ€ 13์ธ ๋ฐ์ดํ„ฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ updatedAt์ด โ€˜2022-08-14 09:53:39โ€™ ์ด๋ฏ€๋กœ ์Šคํ‚ตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
์ž˜๋ชป๋œ ํŽ˜์ด์ง•์œผ๋กœ ๋ฐ์ดํ„ฐ ์œ ์‹ค์ด ๋ฐœ์ƒํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ค‘๋ณต๋˜๋”๋ผ๋„ ๋‹ค๋ฅธ ์ปฌ๋Ÿผ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด ๋‘๋ฒˆ์งธ ๊ทœ์น™์„ ์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
 
๋‹ค๋ฅธ ์ปฌ๋Ÿผ๊ณผ ๊ฒฐํ•ฉํ•ด ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” ์ฟผ๋ฆฌ์— ๊ฐ๋ณ„ํžˆ ์ฃผ์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ปฌ๋Ÿผ์„ ๋‘ ๊ฐœ ์ด์ƒ ์‚ฌ์šฉํ•œ๋‹คํ•ด๋„ ์ฟผ๋ฆฌ๊ฐ€ ์ •ํ™•ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์˜ฌ๋ฐ”๋ฅธ ํŽ˜์ด์ง•์„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
 
์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •์ผ์ด ์ตœ์‹ ์ธ ์ˆœ์œผ๋กœ ํŽ˜์ด์ง•ํ•ด ์ถœ๋ ฅํ•˜๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. updatedAt์ด ๊ฐ™์„ ๊ฒฝ์šฐ์—” ์ค‘๋ณต๋˜์ง€ ์•Š๋Š” ๊ฐ’์ธ pk(id)๋ฅผ ์—ญ์ˆœ์œผ๋กœ ์ •๋ ฌ ํ•ด ์ฟผ๋ฆฌ์— ์กฐ๊ฑด์„ ์ถ”๊ฐ€ ํ•ฉ๋‹ˆ๋‹ค.
notion image
 
  • ์ฟผ๋ฆฌ๋ฅผ ์ž˜ ์งœ์•ผํ•ฉ๋‹ˆ๋‹ค! โ€ผ๏ธ 
3๊ฐœ์”ฉ ํŽ˜์ด์ง• ํ•œ๋‹ค๊ณ  ๊ฐ€์ • ํ–ˆ์„ ๋•Œ, ์ œ๊ฐ€ ์ฒ˜์Œ ์ž‘์„ฑํ–ˆ๋˜ ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์–ผํ• ๋ดค์„ ๋•Œ์—๋Š” ๋ฌธ์ œ ์—†์ด ํŽ˜์ด์ง• ๋˜๋Š” ๋“ฏ ํ•ด ๋ณด์˜€์Šต๋‹ˆ๋‹ค.
SELECT * FROM post WHERE id < ${cursorId} and updatedAt <= ${cursorUpdatedAt} order by updatedAt desc, id desc limit 3;
 
# ์ฒ˜์Œ ๋ฐ์ดํ„ฐ 3๊ฐœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ (๋งˆ์ง€๋ง‰ ๋ฐ์ดํ„ฐ id = 14, updatedAt = 2022-08-14 09:53:39 SELECT * FROM post order by updatedAt desc, id desc limit 3;
notion image
 
# ๋‹ค์Œ ํŽ˜์ด์ง• # cursor -> id = 14, updatedAt = 2022-08-14 09:53:39 # 13, 11, 10 SELECT * FROM post WHERE id < 14 and updatedAt <= '2022-08-14 09:53:39' order by updatedAt desc, id desc limit 3;
notion image
 
# ๋‹ค์Œ ํŽ˜์ด์ง• # cursor -> id = 10, updatedAt = 2022-08-14 08:53:39 # 8, 7, 9 SELECT * FROM post WHERE id < 10 and updatedAt <= '2022-08-14 08:53:39' order by updatedAt desc, id desc limit 3;
notion image
 
 
โš ๏ธ
ํ•˜์ง€๋งŒ ์ด ์ฟผ๋ฆฌ์—๋Š” ๋ฌธ์ œ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. id๋Š” ํ•ญ์ƒ ๋‚ด๋ฆผ์ฐจ์ˆœ์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ผ๋ถ€์˜ ๊ฒŒ์‹œ๋ฌผ์„ Update ํ•˜๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
 
์—ฌ๋Ÿฌ ๊ฒŒ์‹œ๋ฌผ๋“ค์„ ์ˆ˜์ •ํ•ด ๋‹ค์Œ ์ˆœ์„œ์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐฐ์น˜๋œ ๊ฒฝ์šฐ๋ฅผ ์˜ˆ๋กœ ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค.
notion image
 
์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
notion image
์ฒซ๋ฒˆ์งธ ํŽ˜์ด์ง• ํ›„ ์ปค์„œ๋Š” updatedAt = 2022-09-04 12:00:00, id = 1์„ ๊ฐ€๋ฅดํ‚ต๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ๋Š” id๊ฐ€ 1๋ณด๋‹ค ์ž‘์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋“ค์„ ์กฐํšŒํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
 
๊ธฐ์กด ์ฟผ๋ฆฌ๋กœ๋Š” ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค! ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด ๋ณด์ด์ฃ ? ์ฟผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
SELECT * FROM post WHERE updatedAt < ${cursorUpdatedAt} or (id < ${cursorId} and updatedAt == ${cursorUpdatedAt} ORDER BY updatedAt DESC, id DESC LIMIT 3;
 
์ฟผ๋ฆฌ๋ฅผ ๋ณ€๊ฒฝํ•ด์„œ ๋‹ค์‹œ ์ž์„ธํžˆ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
notion image
  1. ์ฒ˜์Œ 3๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค cursor ๋Š” id = 1, updatedAt = 2022-09-04 12:00:00 ์ž…๋‹ˆ๋‹ค.
  1. ๊ทธ ๋‹ค์Œ์€ updatedAt < 2022-09-04 12:00:00 ์กฐ๊ฑด์œผ๋กœ id๊ฐ€ 18, 17, 6 โ€ฆ ์ธ ๊ฐ’์ด ์กฐํšŒ๋˜๊ณ 
    1. 2022-09-04 12:00:00:00๊ณผ ์ค‘๋ณต๋˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค
      ์ด์ œ cursor๋Š” id = 6, updatedAt = 2022-09-04 08:00:00์ž…๋‹ˆ๋‹ค.
  1. ๋‹ค์Œ์œผ๋กœ updatedAt < 2022-09-04 08:00:00 ์กฐ๊ฑด์œผ๋กœ 3-a ๋ถ€๋ถ„์ด ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค.
    1. cursor updatedAt๋ณด๋‹ค ์ž‘์€ ๋ฐ์ดํ„ฐ๋“ค์ž…๋‹ˆ๋‹ค.
      id < 6 AND updatedAt = 2022-09-04 08:00:00 ์กฐ๊ฑด์œผ๋กœ 3-b ๋ถ€๋ถ„์ด ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค.
      cursor updatedAt๊ณผ ๊ฐ™์ง€๋งŒ id๊ฐ€ ๋” ์ž‘์€ ๊ฒƒ ๋“ค์ž…๋‹ˆ๋‹ค. ์ค‘๋ณต ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

REFER