본문 바로가기
C.W.K.
Stream
Lesson 01 of 10 · published

인덱스가 뭐야 — B-tree 설명

~14 min · indexes, b-tree, performance

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

전부의 밑을 받치는 자료구조

인덱스가 없으면 WHERE col = ?은 전부 full table scan이야. SQLite가 row를 하나씩 다 읽고 조건을 검사해서 걸리는 걸 돌려주지. O(n)이야. row가 1000만이면 몇 초가 걸리고, 1만이면 눈에도 안 띄어.

인덱스는 인덱싱한 컬럼을 정렬된 순서로 담고 원래 row로 가는 포인터를 붙여둔 별도의 B-tree야. 인덱스가 있으면 WHERE col = ?이 O(log n)이 돼. 테이블이 아무리 커져도 page를 몇 번만 읽으면 끝나.

SQLite가 B-tree를 타는 방식은 셋이야.

  • EqualityWHERE col = ?이면 맞는 키까지 트리를 타고 내려가.
  • RangeWHERE col BETWEEN a AND b면 첫 지점까지 내려간 다음 거기서부터 쭉 훑어.
  • TEXT의 앞부분 매치WHERE col LIKE 'pre%'는 시작이 정해져 있으니 인덱스를 타. '%suf'는 못 타고.
Principle: INTEGER PRIMARY KEY는 그 자체로 이미 인덱스야. 아무것도 안 했는데 id로 row를 즉시 찾는 게 그래서지. 반면 FK는 자동으로 인덱싱되지 않아. 직접 만들어야 하고, 거의 항상 만들어야 해.

Code

인덱스 유무에 따른 query 동작 변화·sql
CREATE TABLE big(id INTEGER PRIMARY KEY, email TEXT, name TEXT) STRICT;

-- 100k row insert (single transaction!)
WITH RECURSIVE cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt WHERE x<100000)
INSERT INTO big(email, name)
SELECT 'user'||x||'@x.com', 'User '||x FROM cnt;

.timer on
SELECT * FROM big WHERE email = 'user99999@x.com';
-- Run Time: real 0.045 user 0.040 ...   (full scan)

CREATE INDEX idx_big_email ON big(email);
SELECT * FROM big WHERE email = 'user99999@x.com';
-- Run Time: real 0.000 user 0.000 ...   (인덱스 사용)

External links

Exercise

위 demo를 네 머신에서 돌려봐. 그다음 query를 세 개 더 던져. WHERE email LIKE 'user1%', WHERE email LIKE '%@x.com', WHERE email != 'user1@x.com'. .timer on과 EXPLAIN QUERY PLAN으로 인덱스가 어느 걸 돕고 어느 게 scan으로 떨어지는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.