데이터와 보안 ·
데이터베이스 인덱스가 조회를 빠르게 하지만 쓰기 비용을 늘리는 이유
먼저 답부터
데이터베이스 인덱스는 자주 찾는 열의 값과 실제 행 위치를 별도 순서로 정리해 모든 행을 읽지 않고도 후보를 좁히게 합니다. 조회는 빨라질 수 있지만 자료가 추가·수정·삭제될 때 인덱스도 함께 갱신해야 하므로, 실제 쿼리 조건과 실행 계획을 확인해 필요한 인덱스만 두어야 합니다.
데이터베이스 표에 주문이나 회원이 쌓이면 원하는 한 줄을 찾는 일도 점점 무거워질 수 있습니다. 이때 자주 등장하는 인덱스는 책 뒤쪽의 찾아보기처럼, 어떤 값을 어느 위치에서 찾을지 따로 정리한 구조입니다.
찾아보기가 있으면 책을 첫 장부터 전부 읽지 않아도 주제와 쪽 위치를 빠르게 좁힐 수 있습니다. 대신 새 내용을 넣거나 쪽을 옮길 때 찾아보기도 함께 고쳐야 합니다. 데이터베이스 인덱스도 조회 시간을 줄이는 대신 저장 공간과 변경 작업을 더 쓰는 같은 교환 관계를 가집니다.
인덱스는 원본 표와 별도로 만든 찾아보기다
테이블은 행과 열로 데이터를 보관하는 표입니다. 인덱스는 선택한 열의 값과 원본 행을 찾을 단서를 정해진 순서로 따로 보관합니다. PostgreSQL 공식 문서는 인덱스가 특정 행을 훨씬 빠르게 찾게 할 수 있지만 시스템 전체에 추가 부담도 만들기 때문에 신중히 사용해야 한다고 설명합니다.
예를 들어 주문 표에서 주문 번호가 아닌 이메일로 한 사람의 주문을 자주 찾는다고 해 보겠습니다. 이메일 인덱스가 없다면 데이터베이스는 조건에 맞는 행을 찾기 위해 표의 많은 행을 차례로 확인할 수 있습니다. 이메일 인덱스가 있으면 정리된 값에서 후보 위치를 먼저 찾고 필요한 원본 행으로 이동할 수 있습니다.
전체 스캔과 인덱스 조회는 찾는 경로가 다르다
전체 스캔은 테이블의 행을 처음부터 확인하는 방식입니다. 작은 표이거나 대부분의 행을 읽어야 한다면 이 경로가 오히려 단순할 수 있습니다. 인덱스 조회는 정리된 작은 구조에서 조건에 맞는 위치를 좁힌 뒤 원본 행을 가져오는 방식입니다.
SQLite 공식 문서는 인덱스를 원본과 비슷하지만 선택한 열의 값이 앞에 놓이고 그 값 순서로 정리된 별도 표처럼 설명합니다. 중요한 점은 인덱스가 결과를 바꾸지 않는다는 것입니다. 같은 SQL은 같은 데이터를 돌려줘야 하고, 인덱스는 그 답을 찾는 경로만 바꿉니다.
실제 SQL에서 어떤 열을 찾는지 먼저 본다
아래처럼 이메일이 같은 주문만 자주 찾는 쿼리가 있다고 가정해 보겠습니다.
SELECT id, status
FROM orders
WHERE customer_email = 'sample@example.com';
이 경우 후보 인덱스는 customer_email 열과 연결됩니다. 하지만 쿼리가 날짜 범위와 상태를 함께 사용하거나 다른 정렬을 요구한다면 단일 열 인덱스 하나가 가장 알맞다고 바로 단정할 수 없습니다. 여러 열 인덱스에서는 열 순서도 의미가 있으므로 실제로 반복되는 조회 조건부터 적어야 합니다.
예시에 실제 고객 이메일, 주문 번호, 결제 정보는 넣지 않습니다. 문서용 가짜 값과 별도 시험 데이터만 사용합니다.
인덱스가 많으면 입력과 수정도 더 많은 일을 한다
새 행을 추가하면 테이블만 바뀌는 것이 아닙니다. 그 행과 관련된 인덱스에도 새 위치를 반영해야 합니다. 인덱스에 포함된 값을 수정하거나 행을 삭제할 때도 정리 구조를 맞춰야 합니다. 그래서 인덱스가 늘면 저장 공간을 더 쓰고 INSERT, UPDATE, DELETE 작업의 부담이 커질 수 있습니다.
책에 찾아보기 항목을 모든 단어마다 만들면 찾는 선택지는 많아지지만 책 끝부분이 두꺼워지고 본문을 고칠 때 손볼 곳도 늘어납니다. 데이터베이스도 “검색이 느리다”는 이유만으로 모든 열에 인덱스를 추가하면 관리 비용이 커집니다. 자주 쓰지 않는 인덱스는 이득 없이 변경 비용만 더할 수 있습니다.
인덱스가 있어도 데이터베이스가 쓰지 않을 수 있다
데이터베이스의 쿼리 플래너는 SQL을 어떤 순서와 방법으로 처리할지 고르는 기능입니다. 인덱스가 존재한다고 항상 그 경로를 선택하지는 않습니다. 표가 아주 작거나, 조건이 많은 행을 반환하거나, 쿼리 조건이 인덱스 구조와 맞지 않으면 전체 스캔이 더 저렴하다고 판단할 수 있습니다.
PostgreSQL 공식 문서는 실제 쿼리에서 인덱스 사용 여부를 EXPLAIN으로 확인하고, 작은 시험 자료만으로 운영 데이터의 선택을 단정하지 말라고 안내합니다. 인덱스를 만들었다는 사실과 조회가 실제로 빨라졌다는 사실은 구분해야 합니다.
측정은 같은 조건의 실행 계획과 시간으로 비교한다
먼저 느리다고 느낀 화면이 어느 SQL을 실행하는지 찾습니다. 그다음 같은 데이터 범위와 조건에서 변경 전 실행 계획, 읽은 행의 범위, 걸린 시간을 기록합니다. 시험 환경에서 후보 인덱스를 적용한 뒤 같은 방법으로 다시 확인해야 비교가 됩니다.
다음 순서로 판단하면 범위를 좁힐 수 있습니다.
- 사용자가 느리다고 한 실제 기능과 쿼리를 연결합니다.
WHERE,JOIN,ORDER BY에 쓰인 열을 적습니다.- 기존 인덱스와 중복되는지 확인합니다.
- 변경 전 실행 계획과 시간을 저장합니다.
- 운영과 분리된 시험 환경에서 후보를 검토합니다.
- 같은 조건으로 실행 계획과 시간을 다시 비교합니다.
- 조회 이득뿐 아니라 입력·수정 시간과 저장 공간도 확인합니다.
- 기대한 경로가 아니면 인덱스를 더 만들기 전에 통계와 조건을 다시 봅니다.
운영 데이터에서는 생성과 삭제 모두 변경 작업이다
CREATE INDEX는 읽기 전용 점검 명령이 아닙니다. 큰 운영 테이블에서는 오래 걸리거나 잠금과 부하에 영향을 줄 수 있습니다. DROP INDEX도 되돌릴 계획 없이 실행하면 필요한 조회 경로를 없앨 수 있습니다. 문서에서 본 명령을 운영 데이터베이스에 바로 붙여 넣지 마세요.
연결 문자열, 비밀번호, API 키는 명령 기록이나 공개 저장소에 넣지 않습니다. 결제·회원·주문 테이블은 별도 시험 환경과 승인된 백업·복구 절차를 먼저 확인합니다. 정확한 영향 범위를 모르면 실행을 멈추고 데이터베이스 담당자나 호스팅 제공사의 현재 문서를 확인합니다.
오늘 바로 해볼 작은 실습
실제 데이터베이스를 바꾸지 않고 10분 동안 인덱스 후보 점검표를 만듭니다.
- 느리다고 느낀 목록이나 검색 화면 하나를 고릅니다.
- 그 화면이 무엇으로 찾고 무엇으로 정렬하는지 자연어로 적습니다.
- 결과가 한두 행인지 대부분의 행인지 예상 범위를 적습니다.
- 같은 화면에서 자주 바뀌는 값이 무엇인지 적습니다.
- 기존 인덱스를 확인할 위치를 공식 문서에서 찾습니다.
- 변경 전 실행 계획과 시간을 기록할 칸을 만듭니다.
- 조회, 입력, 수정, 저장 공간을 비교할 네 칸을 만듭니다.
- 시험 환경과 운영 환경을 구분해 적습니다.
- 비밀키, 실제 고객 정보, 결제 정보가 메모에 없는지 확인합니다.
- 생성·삭제 명령은 실행하지 않고 담당자 확인 항목으로 남깁니다.
마지막으로 “어떤 쿼리를 빠르게 하려는가, 무엇으로 확인할 것인가, 쓰기 비용은 어디서 늘어나는가”를 각각 한 문장으로 적어 보세요. 세 답이 분명하면 인덱스를 속도 버튼으로 오해하지 않고 실제 사용 흐름에 맞는 도구로 판단할 수 있습니다.
확인한 자료
- Chapter 11. Indexes — PostgreSQL Global Development Group
- Examining Index Usage — PostgreSQL Global Development Group
- Query Planning — SQLite
함께 읽기
- 환경변수와 API 키를 서랍과 금고처럼 구분하는 법
환경변수는 주소나 실행 모드처럼 프로그램 밖에서 바꿀 설정을 담는 서랍이고, API 키는 외부 서비스 사용 권한을 가진 비밀번호에 가깝습니다. 비밀키는 브라우저 코드나 Git 저장소에 넣지 말고 서버의 비밀 저장소에서만 읽도록 해야 합니다.
- 쿠키와 세션과 브라우저 저장소를 보관함 위치로 구분하기
쿠키는 브라우저가 보관하며 조건에 맞는 서버 요청에 함께 보낼 수 있는 작은 값이고, 세션은 보통 서버가 로그인 상태를 보관하고 쿠키에는 연결용 식별자만 두는 방식입니다. localStorage는 같은 출처의 브라우저에 남지만 요청에 자동 첨부되지 않으므로 화면 설정에는 쓸 수 있어도 비밀키 저장소로 보면 안 됩니다.
- SQL로 데이터를 만들고 찾고 고치고 지우는 첫 연습
SQL은 데이터베이스에 말을 거는 문법입니다. INSERT는 새 행을 넣고 SELECT는 조건에 맞는 행을 읽으며 UPDATE는 기존 값을 고치고 DELETE는 행을 지웁니다. 변경 명령은 WHERE 조건이 빠지면 범위가 커질 수 있으므로 같은 조건을 SELECT로 먼저 확인해야 합니다.