본문 바로가기
WIKI 기술 지식 베이스

CREATE INDEX

원문 보기 위키 갱신

CREATE INDEX는 테이블에 인덱스를 만들어 조회, 조인, 정렬의 쿼리 성능을 끌어올려요.

출처: 문서

본문

테이블에 인덱스를 만들어서 조회(lookup), 조인, 정렬에 대한 쿼리 성능을 높여요.

문법

CREATE [UNIQUE] INDEX [IF NOT EXISTS] [schema-name.]index-name
    ON table-name (column-or-expr [COLLATE collation-name] [ASC|DESC], ...)
    [WHERE filter-expression];

설명

CREATE INDEX는 테이블의 하나 이상 컬럼이나 표현식 위에 인덱스를 만들어요. Turso는 SQLite와 같은 형식의 B-tree 인덱스를 써요. 쿼리 플래너는 인덱스가 쿼리를 빠르게 할 수 있을 때 자동으로 인덱스를 활용해요 — SQL 문에서 인덱스를 명시적으로 참조할 필요가 없어요.

매개변수

매개변수 설명
UNIQUE 고유성 제약을 강제해요. 인덱스 컬럼에 중복 값이 생기게 되는 INSERT나 UPDATE는 Turso가 거절해요.
IF NOT EXISTS 같은 이름의 인덱스가 이미 있을 때 오류를 막아줘요. 인덱스가 있으면 문은 아무 것도 하지 않아요.
schema-name 테이블이 들어 있는 붙은(attached) 데이터베이스 이름. 생략하면 main 데이터베이스
index-name 데이터베이스 안에서 고유한 인덱스 이름
table-name 인덱스를 만들 테이블
column-or-expr 인덱스에 넣을 컬럼 이름이나 표현식. 여러 항목은 쉼표로 구분해요.
COLLATE collation-name 인덱스 컬럼에 적용할 선택적 콜레이션 시퀀스 (예: NOCASE).
ASC / DESC 인덱스 컬럼의 정렬 방향. 기본값은 ASC.
WHERE filter-expression 부분(partial) 인덱스를 만드는 선택적 필터. 표현식과 일치하는 행만 인덱스에 들어가요.

컬럼 인덱스

가장 흔한 형태는 하나 이상의 컬럼을 이름으로 인덱싱하는 거예요.

-- Single-column index
CREATE INDEX idx_users_email ON users (email);

-- Multi-column (composite) index
CREATE INDEX idx_orders_customer_date ON orders (customer_id, order_date DESC);

복합(composite) 인덱스는 쿼리가 여러 컬럼으로 필터링하거나 정렬할 때 유용해요. 컬럼 순서가 중요해요 — (a, b) 인덱스는 a만으로 필터링하는 쿼리는 빠르게 해주지만, b만으로 필터링하는 쿼리는 도와주지 못해요.

UNIQUE 인덱스

UNIQUE 인덱스는 인덱스 컬럼에서 같은 값 조합을 가진 행이 둘 이상 있을 수 없게 강제해요. NULL 값들은 서로 다른 것으로 취급되기 때문에, UNIQUE 인덱스는 인덱스 컬럼이 NULL인 행을 여러 개 허용해요.

CREATE UNIQUE INDEX idx_users_email_unique ON users (email);

-- This succeeds:
INSERT INTO users (email) VALUES ('[email protected]');

-- This fails with a UNIQUE constraint violation:
INSERT INTO users (email) VALUES ('[email protected]');

부분 인덱스 (Partial Indexes)

부분 인덱스는 WHERE 절을 만족하는 행만 담아요. 부분 인덱스는 전체 인덱스보다 작고, 항상 같은 필터 조건을 포함하는 쿼리에서 더 효율적이에요.

-- Index only active orders
CREATE INDEX idx_active_orders ON orders (customer_id)
    WHERE status = 'active';

-- The query planner uses this index when the WHERE clause matches
SELECT * FROM orders WHERE status = 'active' AND customer_id = 42;

부분 인덱스의 WHERE 절은 테이블의 아무 컬럼이나 참조할 수 있고, 연산자, 리터럴 값, 내장 함수를 쓸 수 있어요. 서브쿼리는 허용되지 않아요.

표현식 인덱스

표현식 인덱스는 원시 컬럼 값 대신 표현식의 결과를 저장해요. 쿼리가 계산된 값으로 자주 필터링하거나 정렬할 때 표현식 인덱스를 쓰세요.

-- Index on lowercase email for case-insensitive lookups
CREATE INDEX idx_users_email_lower ON users (lower(email));

-- The query planner can use this index for:
SELECT * FROM users WHERE lower(email) = '[email protected]';
-- Index on an arithmetic expression
CREATE INDEX idx_items_total ON items (quantity * unit_price);

인덱스 안의 각 표현식은 인덱싱된 테이블의 컬럼만 참조하는 결정적(deterministic) 표현식이어야 해요. 집계 함수와 서브쿼리는 허용되지 않아요.

커스텀 인덱스 방식

**Turso 확장 기능**: 커스텀 인덱스 방식은 인덱싱을 B-tree 너머로 확장해요. 이 기능은 실험적이며 사용 전에 [활성화](/sql-reference/experimental-features)해야 해요.

Turso는 USING 절로 대안 인덱스 방식을 지정할 수 있게 해줘요.

CREATE INDEX index-name ON table-name USING method-name (columns...);

USING fts로 전문 검색하기

fts 인덱스 방식은 Tantivy로 구동되는 전문 검색 인덱스를 만들어요. FTS 인덱스는 WITH 절을 통해 토크나이저 설정을 지원해요.

-- Basic FTS index
CREATE INDEX idx_articles_search ON articles USING fts (title, body);

-- FTS index with custom tokenizers
CREATE INDEX idx_articles_search ON articles USING fts (
    title WITH tokenizer=simple,
    body WITH tokenizer=ngram
);

FTS 인덱스가 만들어지면 search() 함수로 조회할 수 있어요:

SELECT * FROM articles WHERE search(articles, 'database performance');

예제

흔한 조회 패턴을 위한 인덱스

CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    category TEXT,
    price REAL,
    in_stock INTEGER DEFAULT 1
);

-- Speed up lookups by category
CREATE INDEX idx_products_category ON products (category);

-- Speed up price range queries within a category
CREATE INDEX idx_products_cat_price ON products (category, price);

비즈니스 규칙을 강제하는 유니크 인덱스

CREATE TABLE employees (
    id INTEGER PRIMARY KEY,
    email TEXT NOT NULL,
    department TEXT
);

CREATE UNIQUE INDEX idx_employees_email ON employees (email);

상태 필터를 위한 부분 인덱스

CREATE TABLE tasks (
    id INTEGER PRIMARY KEY,
    assignee TEXT,
    status TEXT DEFAULT 'pending',
    due_date TEXT
);

-- Only index pending tasks -- completed tasks are rarely queried
CREATE INDEX idx_pending_tasks ON tasks (assignee, due_date)
    WHERE status = 'pending';

더 알아보기 (Learn more)

  • DROP INDEX - 인덱스 제거하기
  • REINDEX - 인덱스 다시 만들기
  • CREATE TABLE - 인라인 UNIQUE와 PRIMARY KEY 제약
  • EXPLAIN - 쿼리 계획에서 인덱스 사용 확인