볡합 μΈλ±μŠ€λŠ” μ–Έμ œ ν•„μš”ν• κΉŒ?New

πŸ“š
Backend
2026.08.09

πŸ“š Overview

볡합 μΈλ±μŠ€λŠ” μ—¬λŸ¬ μ»¬λŸΌμ„ λ¬Άμ–΄ μΆ”κ°€ν•˜λ©΄ 쑰회 μ„±λŠ₯이 μ’‹μ•„μ§€λŠ” κΈ°λŠ₯이라고 μƒκ°ν•˜κΈ° 쉽닀.

ν•˜μ§€λ§Œ μ‹€μ œλ‘œλŠ” 컬럼의 κ°œμˆ˜λ³΄λ‹€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 데이터λ₯Ό μ–΄λ–€ 쑰건으둜 μ°Ύκ³ , μ–΄λ–€ μˆœμ„œλ‘œ μ •λ ¬ν•˜λ©°, μ–΄λ–€ λ‹¨μœ„λ‘œ λ‚˜λˆ„μ–΄ λ°˜ν™˜ν•˜λŠ”μ§€κ°€ 더 μ€‘μš”ν•˜λ‹€.

예λ₯Ό λ“€μ–΄ λ‹€μŒκ³Ό 같은 μ‘°νšŒκ°€ μžˆλ‹€κ³  κ°€μ •ν•΄λ³΄μž.

  • νŠΉμ • μƒνƒœ(status)의 λ°μ΄ν„°λ§Œ μ‘°νšŒν•œλ‹€.
  • κΈ°λ³Έ ν‚€(id)λ₯Ό κΈ°μ€€μœΌλ‘œ μ΅œμ‹ μˆœ μ •λ ¬ν•œλ‹€.
  • νŽ˜μ΄μ§€ λ‹¨μœ„λ‘œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.

데이터가 적을 λ•ŒλŠ” 단일 μΈλ±μŠ€λ§ŒμœΌλ‘œλ„ 큰 λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šμ„ 수 μžˆλ‹€. ν•˜μ§€λ§Œ 데이터가 μŒ“μ΄κ³  ν˜ΈμΆœλŸ‰μ΄ μ¦κ°€ν•˜λ©΄, λ°μ΄ν„°λ² μ΄μŠ€λŠ” 인덱슀λ₯Ό μ‚¬μš©ν•˜κ³ λ„ μ΅œμ’… 결과보닀 훨씬 λ§Žμ€ 데이터λ₯Ό μ½κ±°λ‚˜ λ³„λ„μ˜ μ •λ ¬ μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ²Œ λœλ‹€.

κ·Έλ ‡λ‹€λ©΄ 볡합 μΈλ±μŠ€λŠ” μ–΄λ–€ μƒν™©μ—μ„œ ν•„μš”ν•˜κ³ , μ–΄λ–€ κΈ°μ€€μœΌλ‘œ 섀계해야 ν• κΉŒ?



1. 볡합 μΈλ±μŠ€κ°€ ν•„μš”ν•˜λ‹€λŠ” μ‹ ν˜Έ


μ²˜μŒλΆ€ν„° λͺ¨λ“  쑰회 쑰건을 볡합 인덱슀둜 λ§Œλ“€ ν•„μš”λŠ” μ—†λ‹€.

μš°μ„  운영 ν™˜κ²½μ—μ„œ μ‹€μ œλ‘œ 느린 μš”μ²­μ„ μ°Ύκ³ , ν•΄λ‹Ή μš”μ²­μ΄ μ–΄λ–€ λ°©μ‹μœΌλ‘œ 데이터λ₯Ό μ½λŠ”μ§€ ν™•μΈν•˜λŠ” 것이 λ¨Όμ €λ‹€.

μ‹€ν–‰ κ³„νšμ—μ„œλŠ” λ‹€μŒκ³Ό 같은 μ‹ ν˜Έλ₯Ό μ‚΄νŽ΄λ³Ό 수 μžˆλ‹€.

  • 전체 ν…Œμ΄λΈ”μ„ ν™•μΈν•˜κ³  μžˆλŠ” 경우
  • 인덱슀λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ ν•„μš”ν•œ 결과보닀 훨씬 λ§Žμ€ 행을 μ½λŠ” 경우
  • λ³„λ„μ˜ μ •λ ¬ μž‘μ—…μ΄λ‚˜ μž„μ‹œ ν…Œμ΄λΈ”μ„ μ‚¬μš©ν•˜λŠ” 경우
  • 데이터가 μ¦κ°€ν• μˆ˜λ‘ 응닡 μ‹œκ°„μ΄ ν•¨κ»˜ μ¦κ°€ν•˜λŠ” 경우

예λ₯Ό λ“€μ–΄ λ‹€μŒκ³Ό 같은 쿼리가 μžˆλ‹€κ³  ν•΄λ³΄μž.

SELECT id, status, title
FROM posts
WHERE status = 'PUBLISHED'
ORDER BY id DESC
LIMIT 20;

status에 단일 μΈλ±μŠ€κ°€ μžˆλ‹€λ©΄ λ°μ΄ν„°λ² μ΄μŠ€λŠ” PUBLISHED μƒνƒœμ˜ 데이터λ₯Ό μ°ΎλŠ” λ°μ—λŠ” 도움을 받을 수 μžˆλ‹€.

ν•˜μ§€λ§Œ ν•΄λ‹Ή λ²”μœ„μ—μ„œ λ‹€μ‹œ id κΈ°μ€€μœΌλ‘œ μ •λ ¬ν•΄μ•Ό ν•œλ‹€λ©΄, 쑰건에 λ§žλŠ” 데이터λ₯Ό 더 많이 읽은 λ’€ μ •λ ¬ν•˜λŠ” μž‘μ—…μ΄ 좔가될 수 μžˆλ‹€. κ²°κ³ΌλŠ” 20건뿐인데 λ°μ΄ν„°λ² μ΄μŠ€κ°€ 그보닀 훨씬 λ§Žμ€ 행을 ν™•μΈν•˜κ³  μžˆλ‹€λ©΄, ν˜„μž¬ μΈλ±μŠ€κ°€ μ‹€μ œ 쑰회 경둜λ₯Ό μΆ©λΆ„νžˆ ν‘œν˜„ν•˜μ§€ λͺ»ν•˜κ³  μžˆμ„ κ°€λŠ₯성이 μžˆλ‹€.



2. 쑰회 κ²½λ‘œμ— λ§žλŠ” 볡합 인덱슀


μ•žμ„  쑰회 쑰건과 μ •λ ¬ μˆœμ„œλ₯Ό ν•¨κ»˜ κ³ λ €ν•˜λ©΄ λ‹€μŒκ³Ό 같은 인덱슀λ₯Ό ν›„λ³΄λ‘œ κ²€ν† ν•  수 μžˆλ‹€.

CREATE INDEX idx_posts_status_id
ON posts (status, id DESC);

이 μΈλ±μŠ€λŠ” λ¨Όμ € status 쑰건으둜 쑰회 λ²”μœ„λ₯Ό 쒁힌 λ’€, ν•΄λ‹Ή λ²”μœ„ μ•ˆμ—μ„œ id μˆœμ„œλŒ€λ‘œ 데이터λ₯Ό 탐색할 수 μžˆλ„λ‘ μ„€κ³„ν•œ 것이닀.

즉, λ°μ΄ν„°λ² μ΄μŠ€κ°€ λ‹€μŒ 두 μž‘μ—…μ„ ν•˜λ‚˜μ˜ 인덱슀 κ²½λ‘œμ—μ„œ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ λ•λŠ”λ‹€.

  • status = 'PUBLISHED' 쑰건으둜 λŒ€μƒ λ²”μœ„ 쒁히기
  • ν•΄λ‹Ή λ²”μœ„μ—μ„œ id DESC μˆœμ„œλ‘œ 데이터 νƒμƒ‰ν•˜κΈ°

λ‹€λ§Œ idκ°€ 항상 μ‹€μ œ 생성 μ‹œκ°„μ˜ μˆœμ„œλ₯Ό μ˜λ―Έν•˜λŠ” 것은 μ•„λ‹ˆλ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ΅œμ‹ μˆœμ„ ν‘œν˜„ν•˜λ €λŠ” λͺ©μ μ΄λΌλ©΄ created_at이 더 μ •ν™•ν•œ μ •λ ¬ 기쀀일 μˆ˜λ„ μžˆλ‹€.

CREATE INDEX idx_posts_status_created_at
ON posts (status, created_at DESC, id DESC);

λ™μΌν•œ 생성 μ‹œκ°μ„ κ°€μ§„ λ°μ΄ν„°μ˜ μˆœμ„œλ₯Ό μ•ˆμ •μ μœΌλ‘œ μœ μ§€ν•˜λ €λ©΄ idλ₯Ό 보쑰 μ •λ ¬ κΈ°μ€€μœΌλ‘œ ν•¨κ»˜ μ‚¬μš©ν•˜λŠ” 방식도 κ³ λ €ν•  수 μžˆλ‹€.

볡합 μΈλ±μŠ€λŠ” λ‹¨μˆœνžˆ μ»¬λŸΌμ„ μ—¬λŸ¬ 개 μΆ”κ°€ν•˜λŠ” κΈ°λŠ₯이 μ•„λ‹ˆλ‹€. μ‹€μ œ 쿼리의 WHERE, ORDER BY, LIMIT이 μ–΄λ–€ μˆœμ„œλ‘œ μ—°κ²°λ˜λŠ”μ§€λ₯Ό μΈλ±μŠ€μ— ν‘œν˜„ν•˜λŠ” 섀계에 가깝닀.



3. 컬럼의 μˆœμ„œκ°€ μ€‘μš”ν•œ 이유


특히 (status, id)와 (id, status)λŠ” μ„œλ‘œ λ‹€λ₯Έ μΈλ±μŠ€λ‹€.

두 인덱슀 λͺ¨λ‘ 같은 μ»¬λŸΌμ„ ν¬ν•¨ν•˜κ³  μžˆμ§€λ§Œ, λ°μ΄ν„°λ² μ΄μŠ€κ°€ 인덱슀λ₯Ό νƒμƒ‰ν•˜λŠ” 방식은 달라진닀.

-- μƒνƒœλ‘œ λ²”μœ„λ₯Ό 쒁힌 λ’€ id μˆœμ„œλ‘œ 쑰회
(status, id)

-- id μˆœμ„œκ°€ μš°μ„ μΈ 인덱슀
(id, status)

(status, id)λŠ” statusκ°€ 쑰회의 μ‹œμž‘ 쑰건으둜 μ‚¬μš©λ˜λŠ” νŒ¨ν„΄μ— μ ν•©ν•˜λ‹€. 반면 (id, status)λŠ” idκ°€ λ¨Όμ € μ •λ ¬μ΄λ‚˜ λ²”μœ„ 쑰건에 μ‚¬μš©λ˜λŠ” νŒ¨ν„΄μ—μ„œ 더 μžμ—°μŠ€λŸ½κ²Œ ν™œμš©λ  수 μžˆλ‹€.

볡합 인덱슀의 μ•žμͺ½ μ»¬λŸΌμ„ μƒλž΅ν•˜λ©΄ λ’€μͺ½ μ»¬λŸΌλ§ŒμœΌλ‘œλŠ” 인덱슀λ₯Ό μ›ν•˜λŠ” λ°©μ‹μœΌλ‘œ ν™œμš©ν•˜κΈ° μ–΄λ €μšΈ 수 μžˆλ‹€. λ”°λΌμ„œ 자주 μ‚¬μš©ν•˜λŠ” μ»¬λŸΌμ„ 아무 μˆœμ„œλ‘œλ‚˜ λ‚˜μ—΄ν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œλŠ” μΆ©λΆ„ν•˜μ§€ μ•Šλ‹€.

λ‹€μŒκ³Ό 같은 λ‚΄μš©μ„ ν•¨κ»˜ 확인해야 ν•œλ‹€.

  • μ‹€μ œ WHERE 쑰건이 무엇인지
  • ORDER BY의 컬럼과 λ°©ν–₯이 무엇인지
  • νŽ˜μ΄μ§€ λ‹¨μœ„ μ‘°νšŒκ°€ OFFSET κΈ°λ°˜μΈμ§€ μ»€μ„œ κΈ°λ°˜μΈμ§€
  • 첫 번째 인덱슀 컬럼이 μ‹€μ œ μ‘°νšŒμ—μ„œ 항상 μ‚¬μš©λ˜λŠ”μ§€
  • 쑰건의 선택도와 데이터 뢄포가 μ–΄λ–€μ§€

νŽ˜μ΄μ§€κ°€ κΉŠμ–΄μ§ˆμˆ˜λ‘ OFFSET 기반 μ‘°νšŒλŠ” μ•žμ„  데이터λ₯Ό κ±΄λ„ˆλ›°κΈ° μœ„ν•΄ 더 λ§Žμ€ 행을 확인할 수 μžˆλ‹€. 이런 κ²½μš°μ—λŠ” λ§ˆμ§€λ§‰μœΌλ‘œ μ‘°νšŒν•œ idλ₯Ό κΈ°μ€€μœΌλ‘œ λ‹€μŒ νŽ˜μ΄μ§€λ₯Ό κ°€μ Έμ˜€λŠ” μ»€μ„œ 기반 μ‘°νšŒλ„ ν•¨κ»˜ κ²€ν† ν•  수 μžˆλ‹€.

SELECT id, status, title
FROM posts
WHERE status = 'PUBLISHED'
  AND id < 1200
ORDER BY id DESC
LIMIT 20;

이 쿼리 μ—­μ‹œ (status, id DESC) μΈλ±μŠ€κ°€ 쑰회 쑰건과 μ •λ ¬ μˆœμ„œλ₯Ό ν‘œν˜„ν•˜λŠ” 데 도움을 쀄 수 μžˆλ‹€.



4. μ‹€ν–‰ κ³„νšκ³Ό 운영 ν™˜κ²½μ—μ„œ κ²€μ¦ν•˜κΈ°


볡합 μΈλ±μŠ€λŠ” 개발 λ‹¨κ³„μ—μ„œ 미리 μΆ”κ°€ν•œλ‹€κ³  항상 쒋은 κ²°κ³Όλ₯Ό 보μž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.

인덱슀λ₯Ό μΆ”κ°€ν•˜κΈ° μ „μ—λŠ” λ¨Όμ € μ‹€μ œ μ‹€ν–‰ κ³„νšμ„ ν™•μΈν•œλ‹€.

EXPLAIN ANALYZE
SELECT id, status, title
FROM posts
WHERE status = 'PUBLISHED'
ORDER BY id DESC
LIMIT 20;

μ΄λ•Œ λ‹¨μˆœνžˆ 인덱슀 이름이 ν‘œμ‹œλ˜λŠ”μ§€λ§Œ 보지 μ•Šκ³ , μ˜ˆμƒν•œ 쑰회 κ²½λ‘œκ°€ μ‹€μ œλ‘œ μ‚¬μš©λ˜μ—ˆλŠ”μ§€ 확인해야 ν•œλ‹€.

  • μ˜ˆμƒν•œ 인덱슀λ₯Ό μ‚¬μš©ν•˜λŠ”κ°€?
  • μ‹€μ œλ‘œ 읽은 ν–‰μ˜ μˆ˜κ°€ μ€„μ—ˆλŠ”κ°€?
  • μ •λ ¬μ΄λ‚˜ μž„μ‹œ ν…Œμ΄λΈ”μ΄ μ‚¬λΌμ‘ŒλŠ”κ°€?
  • 응닡 μ‹œκ°„μ΄ κ°œμ„ λ˜μ—ˆλŠ”κ°€?
  • νŠΉμ • 데이터 λΆ„ν¬μ—μ„œλ§Œ μ’‹μ•„μ§„ 것은 μ•„λ‹Œκ°€?

인덱슀 μΆ”κ°€μ—λŠ” λΉ„μš©λ„ μžˆλ‹€.

  • μ €μž₯ 곡간을 μΆ”κ°€λ‘œ μ‚¬μš©ν•œλ‹€.
  • INSERT, UPDATE, DELETE μ‹œ μΈλ±μŠ€λ„ ν•¨κ»˜ κ°±μ‹ ν•΄μ•Ό ν•œλ‹€.
  • μΈλ±μŠ€κ°€ λ§Žμ•„μ§ˆμˆ˜λ‘ 데이터 λ³€κ²½ λΉ„μš©κ³Ό 관리 λΉ„μš©μ΄ μ¦κ°€ν•œλ‹€.
  • μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” μΈλ±μŠ€κ°€ μŒ“μ΄λ©΄ μ–΄λ–€ 인덱슀λ₯Ό μœ μ§€ν•΄μ•Ό ν•˜λŠ”μ§€ νŒλ‹¨ν•˜κΈ° μ–΄λ €μ›Œμ§„λ‹€.

λ”°λΌμ„œ 인덱슀λ₯Ό μΆ”κ°€ν•œ λ’€μ—λŠ” 같은 쑰건으둜 λ‹€μ‹œ μΈ‘μ •ν•˜κ³ , μ‹€μ œ 운영 μš”μ²­μ˜ 응닡 μ‹œκ°„κ³Ό λ°μ΄ν„°λ² μ΄μŠ€ λΆ€ν•˜κ°€ κ°œμ„ λ˜μ—ˆλŠ”μ§€ 확인해야 ν•œλ‹€.

AIλŠ” 쿼리λ₯Ό λΆ„μ„ν•˜κ³  인덱슀 후보λ₯Ό μ œμ•ˆν•˜κ±°λ‚˜ μ‹€ν–‰ κ³„νšμ„ ν•΄μ„ν•˜λŠ” 데 도움을 쀄 수 μžˆλ‹€. ν•˜μ§€λ§Œ μ–΄λ–€ μš”μ²­μ΄ 운영 ν™˜κ²½μ—μ„œ μ€‘μš”ν•œμ§€, ν˜„μž¬ μ„±λŠ₯ μ €ν•˜κ°€ μ‚¬μš©μž κ²½ν—˜μ— μ–΄λ–€ 영ν–₯을 μ£ΌλŠ”μ§€, 인덱슀 μΆ”κ°€ λΉ„μš©μ„ 감당할 수 μžˆλŠ”μ§€λŠ” μ½”λ“œλ§Œ 보고 νŒλ‹¨ν•˜κΈ° μ–΄λ ΅λ‹€.



πŸ€” Understanding

볡합 μΈλ±μŠ€κ°€ ν•„μš”ν•œ μˆœκ°„μ€ 컬럼이 μ—¬λŸ¬ 개 μ‚¬μš©λ  λ•Œκ°€ μ•„λ‹ˆλΌ, μ‹€μ œ 쑰회 κ²½λ‘œκ°€ κΈ°μ‘΄ 인덱슀만으둜 효율적으둜 ν‘œν˜„λ˜μ§€ μ•Šμ„ λ•ŒλΌκ³  μƒκ°ν•œλ‹€.

λ¨Όμ € 운영 ν™˜κ²½μ—μ„œ 느린 μš”μ²­μ„ μ°Ύκ³ , μ‹€ν–‰ κ³„νšμ„ 톡해 λ°μ΄ν„°λ² μ΄μŠ€κ°€ μ–Όλ§ˆλ‚˜ λ§Žμ€ 데이터λ₯Ό μ½λŠ”μ§€ 확인해야 ν•œλ‹€. κ·Έλ‹€μŒ μ‹€μ œ 쑰회 쑰건과 μ •λ ¬, νŽ˜μ΄μ§€ λ‹¨μœ„ 쑰회 방식에 맞좰 인덱슀λ₯Ό μ„€κ³„ν•˜κ³  적용 ν›„ 같은 μ‘°κ±΄μ—μ„œ λ‹€μ‹œ μΈ‘μ •ν•΄μ•Ό ν•œλ‹€.

볡합 인덱슀의 컬럼 μˆœμ„œλ„ μ€‘μš”ν•˜μ§€λ§Œ, 그보닀 λ¨Όμ € ν•΄κ²°ν•˜λ €λŠ” 쑰회 νŒ¨ν„΄μ΄ λΆ„λͺ…ν•΄μ•Ό ν•œλ‹€. (status, id)와 (id, status) 쀑 μ–΄λŠ μͺ½μ΄ 더 μ’‹μ€μ§€λŠ” 인덱슀 μžμ²΄κ°€ μ•„λ‹ˆλΌ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 데이터λ₯Ό μ°ΎλŠ” 방식에 따라 달라진닀.

AIκ°€ μ½”λ“œλ₯Ό λΉ λ₯΄κ²Œ κ΅¬ν˜„ν•΄μ£ΌλŠ” μ‹œλŒ€μΌμˆ˜λ‘ 운영 ν™˜κ²½μ„ κ΄€μ°°ν•˜κ³  μ‹€μ œ 병λͺ©μ„ μ •μ˜ν•˜λ©° κ°œμ„  μ „ν›„λ₯Ό κ²€μ¦ν•˜λŠ” 개발자의 역할은 더 μ€‘μš”ν•΄μ§€κ³  μžˆλ‹€.

κ²°κ΅­ μΈλ±μŠ€λŠ” 많이 μΆ”κ°€ν•˜λŠ” 것이 λͺ©ν‘œκ°€ μ•„λ‹ˆλΌ, λ°˜λ³΅λ˜λŠ” 쑰회 경둜λ₯Ό 적은 λΉ„μš©μœΌλ‘œ ν‘œν˜„ν•˜λŠ” 도ꡬ에 가깝닀.

Previous
Conductorμ—μ„œ Supersets둜 μ •μ°©ν•œ 이유
πŸ€–AI
2026.06.21