Skip to content

[Feat] 하이브리드 방식 인덱스 개선 및 비교#35

Merged
1024andrew merged 3 commits intodevfrom
feat/#31
May 5, 2026
Merged

[Feat] 하이브리드 방식 인덱스 개선 및 비교#35
1024andrew merged 3 commits intodevfrom
feat/#31

Conversation

@kimssirr
Copy link
Copy Markdown
Contributor

@kimssirr kimssirr commented May 4, 2026

유형

  • Feat
  • Fix
  • Design
  • Docs
  • Chore
  • Hotfix

작업 내용

하이브리드 검색의 키워드 검색 성능 개선을 위해 regulation_chunk에 검색용 tsvector 컬럼을 추가하고, 해당 컬럼에 GIN 인덱스를 적용했습니다.

기존에는 검색 시점마다 chunk_text, regulation_document.content, keywords를 조합해 to_tsvector(...)를 반복 계산했는데, 이제 검색 대상 텍스트를 미리 search_tsvector에 저장하고 인덱스를 통해 조회하도록 변경했습니다.
변경사항은 노션 백엔드 - 디비 문서에 정리했습니다.

또한 개선 전후 성능을 비교할 수 있도록 하이브리드 검색 벤치마크 스크립트를 추가했습니다.

변경 사항 (있다면)

  • regulation_chunk.search_tsvector 컬럼 추가
  • idx_regulation_chunk_search_tsvector GIN 인덱스 추가
  • 기존 regulation_chunk 데이터에 대한 search_tsvector backfill migration 추가
  • 하이브리드 검색 SQL에서 반복 계산하던 to_tsvector(...)rc.search_tsvector 사용으로 변경
  • 신규 chunk 생성 시 search_tsvector가 갱신되도록 처리
  • 하이브리드 검색 성능 측정 스크립트 추가
  • DB schema 및 repository 테스트 보강

성능 비교

이번 변경은 전체 챗봇 응답 시간이 아니라 하이브리드 검색 DB 조회 구간을 최적화한 변경입니다. 따라서 성능 비교는 repository 함수 실행 시간과 PostgreSQL EXPLAIN 실행계획을 기준으로 진행했습니다.

동일한 20개 질문 케이스에 대해 개선 전후 하이브리드 검색 benchmark를 실행했습니다.

측정 조건:

  • case_count: 20
  • iterations: 50
  • warmup: 5
  • active_chunk_count: 135
  • embedding_mode: anchor

결과 요약:

  • 평균 응답 시간: 11.351ms → 5.979ms (-47.3%)
  • p95 응답 시간: 12.395ms → 7.020ms (-43.4%)
  • EXPLAIN execution time: 8.127ms → 1.902ms (-76.6%)
  • 상위 검색 결과 regulation_chunk_id 변경: 0건

실행계획 변화:

  • 개선 전: GIN 인덱스 미사용, Seq Scan 중심
  • 개선 후: idx_regulation_chunk_search_tsvector 사용, keyword branch에서 Bitmap Index Scan 확인

리뷰 포인트

  • migration에서 search_tsvector 컬럼 추가, backfill, GIN 인덱스 생성 순서가 적절한지
  • 하이브리드 검색 SQL이 기존 검색 의미를 유지하면서 rc.search_tsvector를 사용하도록 변경됐는지
  • 신규 chunk 생성 시 search_tsvector 갱신 로직이 누락 없이 동작하는지
  • 운영 DB 적용 시 일반 CREATE INDEX 사용이 현재 데이터 규모와 운영 방식에 적절한지

리뷰 반영 요약

  • search_tsvector 생성 방식 개선

    • 기존에는 chunk INSERT 후 별도 UPDATE로 search_tsvector를 채웠습니다.
    • 생성 시점에 이미 chunk_text, document.content, keywords를 가지고 있으므로 INSERT 시 func.to_tsvector(...)를 함께 저장하도록 변경했습니다.
    • 불필요한 DB round trip과 join UPDATE 비용을 줄이기 위함입니다.
  • 기존 데이터 backfill 방식 개선

    • 전체 row를 한 번에 UPDATE하지 않고 regulation_chunk_id 기준 batch 단위로 나눠 갱신하도록 변경했습니다.
    • 운영 DB에서 WAL 부하와 긴 UPDATE 실행 시간을 줄이기 위함입니다.
  • keyword 검색 텍스트 정리

    • rc.keywords::text 대신 keyword 배열 원소를 공백으로 합쳐 검색 벡터에 포함하도록 변경했습니다.
    • JSON 배열 문법이 검색 텍스트에 섞이지 않도록 하기 위함입니다.
  • 확장 쿼리 embedding 재사용

    • 이미 pre-expand 단계에서 생성한 rewritten_query embedding이 있으면 fallback query expansion 검색에서 재사용하도록 변경했습니다.
    • 같은 query에 대한 중복 embedding API 호출을 막기 위함입니다.

테스트

  • 로컬 실행 확인
  • /docs 수동 확인
  • pytest 실행

스크린샷

@kimssirr kimssirr self-assigned this May 4, 2026
@kimssirr kimssirr added the feat 구현·개선 사항에 관련된 내용입니다. label May 4, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a search_tsvector column to the regulation_chunk table to optimize hybrid search performance by pre-calculating search vectors. It includes database migrations, model updates, and logic in the repository to utilize the new column. Feedback focuses on optimizing the data population process to reduce database round trips, improving migration safety for large datasets by using concurrent index creation and batching updates, and eliminating redundant embedding API calls in the chat service logic.

Comment thread app/repositories/regulation_chunk_repository.py
Comment thread app/services/chat_service.py
Comment thread app/services/chat_service.py
@1024andrew 1024andrew merged commit 56fbe15 into dev May 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 구현·개선 사항에 관련된 내용입니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants