데이터베이스 LIKE문 제대로 이해하고 사용하기

데이터베이스 LIKE문 제대로 이해하고 사용하기

데이터베이스 검색 쿼리를 작성하다 보면 텍스트 일치 확인이 필요한 순간이 자주 찾아옵니다. 키워드 자동완성 기능을 구현하거나, 사용자가 작성한 글에서 특정 키워드가 포함되어 있는지 확인하는 등 다양한 상황에서 LIKE 문을 사용하게 됩니다.

하지만 LIKE 문을 잘못 사용하면 전체 데이터를 스캔하는 Full Table Scan이 발생하여 심각한 성능 이슈로 이어질 수 있습니다.


LIKE 문의 성능 문제

LIKE 문은 패턴 매칭을 통해 텍스트를 검색하는 강력한 기능이지만, 와일드카드(%)의 위치에 따라 성능이 천차만별로 달라집니다.

인덱스를 활용할 수 없는 경우

검색어의 앞이나 양쪽에 %를 사용하면, 인덱스를 생성해두었더라도 데이터베이스는 인덱스를 활용하지 못하고 전체 테이블을 스캔하게 됩니다.

-- 나쁜 예시
SELECT * FROM member WHERE username LIKE '%mike%';
SELECT * FROM member WHERE username LIKE '%mike';

인덱스는 데이터가 정렬된 상태로 저장되어 있습니다. 하지만 검색어 앞에 %가 붙으면 어떤 문자로 시작하는지 알 수 없기 때문에 인덱스의 정렬 순서를 활용할 수 없게 됩니다.

인덱스를 활용할 수 있는 경우 반면 검색어 뒤에만 %를 사용하면 인덱스를 효과적으로 활용할 수 있습니다.

-- 좋은 예시
SELECT * FROM member WHERE username LIKE 'mike%';

이 경우 ‘mike’로 시작하는 모든 데이터를 찾는 것이므로, 인덱스의 정렬 순서를 따라 빠르게 검색할 수 있습니다.


최적화 방법

1. 인덱스 추가

LIKE문을 사용하는 컬럼에는 반드시 인덱스를 추가해야 합니다.

CREATE INDEX idx_username ON member(username);

2. 와일드카드 위치 조정

검색 요구사항을 분석하여 가능하다면 접두사 검색형태로 변경합니다.

  • 접두사 검색: ‘mike%’ – 인덱스 활용 가능
  • 중간 검색: ‘%mike%’ – 인덱스 활용 불가
  • 접미사 검색: ‘%mike’ – 인덱스 활용 불가 3. 성능 차이 체감하기

실제로 100만 건의 데이터가 있는 테이블에서 테스트해보면:

  • username LIKE ‘mike%’ (인덱스 활용): 0.01초
  • username LIKE ‘%mike%’ (Full Scan): 2.5초

3. Full-Text Search 활용하기

만약 중간 검색이나 접미사 검색이 필수적이라면 Full-Text Search를 고려할 수 있습니다.

Full-Text Search란?

Full-Text Search는 일반 B-Tree 인덱스와는 다른 전용 FULLTEXT 인덱스를 사용하는 검색 방식입니다. 역색인(Inverted Index) 구조를 통해 텍스트를 단어 단위로 분해하고, 각 단어가 어느 문서에 나타나는지 매핑합니다.

-- FULLTEXT 인덱스 생성
CREATE FULLTEXT INDEX idx_content ON articles(content);

-- 일반 LIKE (인덱스 활용 불가)
SELECT * FROM articles WHERE content LIKE '%데이터베이스%';

-- FULLTEXT 검색 (FULLTEXT 인덱스 활용)
SELECT * FROM articles WHERE MATCH(content) AGAINST('데이터베이스' IN NATURAL LANGUAGE MODE);
Full-Text Search의 장점
  • 중간 검색(%keyword%) 패턴도 효율적으로 처리
  • 관련도(relevance) 기반 정렬 가능
  • 불용어(stopwords) 처리 자동화
Full-Text Search의 성능 이슈

1. 인덱스 크기 문제

FULLTEXT 인덱스는 텍스트 데이터를 단어 단위로 분해하여 저장하기 때문에 원본 테이블 크기의 50~100%까지 인덱스 크기가 증가할 수 있습니다. 이는 디스크 공간 소모와 메모리 부족으로 이어질 수 있습니다.

2. INSERT/UPDATE 성능 저하

새로운 데이터를 추가하거나 수정할 때마다 텍스트를 단어로 분해하고 역색인을 업데이트해야 하므로 일반 인덱스보다 쓰기 작업이 느립니다. 쓰기 작업이 많은 시스템에서는 병목 현상이 발생할 수 있습니다.

3. 복잡한 검색 쿼리

   SELECT * FROM articles
   WHERE MATCH(content) AGAINST('+데이터베이스 +최적화 -느림' IN BOOLEAN MODE)
   AND created_at > '2024–01–01'
   ORDER BY relevance DESC
   LIMIT 1000;

여러 조건을 조합하거나 매칭되는 문서가 수만~수십만 건인 경우 여전히 성능 저하가 발생할 수 있습니다.

4. 한글 처리 문제

기본 Full-Text Search는 영어에 최적화되어 있습니다. 한글을 제대로 처리하려면 ngram 파서를 사용해야 합니다.

CREATE FULLTEXT INDEX idx_content ON articles(content) WITH PARSER ngram;

마무리

LIKE 문은 간단하고 직관적이지만, 잘못 사용하면 서비스 전체의 성능에 악영향을 미칠 수 있습니다.

핵심 원칙을 정리하면 검색 컬럼에 인덱스를 생성하고 와일드카드는 검색어 뒤에만 사용하세요. 중간 검색이 필수라면 데이터 규모와 쓰기 빈도를 고려하여 Full-Text Search나 전문 검색 엔진을 선택하세요




    Enjoy Reading This Article?

    Here are some more articles you might like to read next:

  • 데이터베이스 관계키(FK) 는 꼭 사용해야 할까?
  • 데이터베이스 인덱스 동작방식 그리고 최적화
  • 대용량 디비에 파티션을 활용해야 하는 이유
  • 무료 프록시, 크롤러 실패의 지름길, 유료 프록시가 필수인 7가지 기술적 이유
  • 파이썬 웹 크롤링 완벽 가이드 - 현업 데이터 엔지니어의 실전 노하우