강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

dltkdcksqkqh님의 프로필 이미지
dltkdcksqkqh

작성한 질문수

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

섹션 2 퀴즈

정렬, 필터, 검색 등의 조건이 붙을 경우 최적화할 수 있는 방법이 무엇이 있을까요?

해결된 질문

작성

·

27

0

안녕하세요.
게시판 관련 강의를 듣는 도중 궁금한 점이 있어 질문을 남깁니다.

강의에서는 Snowflake 기반 단순 정렬을 기준으로 커버링 인덱스를 설명해주셨는데요,
실무에서는 여러 정렬 조건과 필터, 검색 조건이 함께 붙는 경우가 많습니다.

이런 복합적인 조회 패턴에서도 커버링 인덱스를 중심으로 설계하는 것이 적절한지,
아니면 다른 전략을 어떻게 사용해야 하는지 궁금합니다.(설명이 길어질 경우 간단한 힌트라도 부탁드립니다.)


💥 걱정하는 부분

  • 정렬되는 컬럼 전부에 대해 인덱스를 걸면 더 문제가 발생할 것 같아요.

  • 검색 %검색어%의 경우에는 결국엔 full_scan이어서 성능 최적화가 불가능하다.

답변 2

0

쿠케님의 프로필 이미지
쿠케
지식공유자

dltkdcksqkqh님, 안녕하세요!

 

인덱스의 동작 원리를 정확히 이해하고 있으면, 다른 쿼리도 동일한 방식으로 최적화할 수 있습니다.

반드시 커버링 인덱스를 사용해야하는 것도 아닙니다.

offset 스캔에 대한 우려가 없다면 단일 쿼리로 처리할 수도 있는 것이고요.

이 부분은 다른 쿼리 방식도 한번 직접 고민하며 만들어보셔도 좋을 것 같네요!

아래 질문들에 대한 답변으로 궁금증들이 어느 정도 해소되길 바랍니다.

 

정렬되는 컬럼 전부에 대해 인덱스를 걸면 더 문제가 발생할 것 같아요.

인덱스를 걸면 추가적인 관리 비용이 생기기 때문에, 반드시 만들어야 하는 것인지부터 고민이 필요합니다.

데이터 종류, 규모, 조회 패턴 등을 고려해볼 수 있을 것 같은데요.

몇 가지 예시를 보겠습니다.

 

첫째로, 인덱스 range scan하면서 어느 정도는 조회 시점에 필터링하는 것도 충분할 수도 있는 상황인데요.

각 게시글에 해시태그를 설정할 수 있고, 등록 가능한 수가 최대 10개라고만 가정해보겠습니다.

해시태그 테이블을 간단히 정의하면, hashtag_id(pk), article_id(fk), hashtag_name 이렇게 구성될 수 있을 것이고요.

그리고 게시글에 특정한 해시태그명이 이미 작성되어 있는지 확인하려면,

article_id + hashtag_name로 쿼리가 필요할 수 있습니다.

그런데 이러한 쿼리를 수행하기 위해서 (article_id, hashtag_name) 인덱스가 반드시 필요할지 고민해볼 수 있을 것 같습니다.

어차피 시스템 제약으로 게시글의 해시태그는 최대 10건인 상황입니다.

즉, article_id로만 필터링해도 10건 정도는 전체 스캔 해와도 메모리 내에서 빠르게 처리할 수 있으므로, 굳이 hashtag_name까지 인덱스에 포함하지 않을 수 있겠습니다.

 

또, 인덱스를 만들지 않고 테이블 풀스캔하는 것이 적절한 상황도 있습니다.

게시글을 작성할 수 있는 게시판이라는 개념을 생각해보겠습니다.

이 게시판은 생성/수정/삭제가 엄청나게 잦지만(쓰기 작업이 엄청 잦다는 예시에 게시판이 적절할지는 모르겠지만 그 부분은 차치하고 대략적인 맥락만 이해해주시면 됩니다!),

어차피 사용자가 실제 선택하고 활용할만한 게시판은 최대 수 천개 내에서만 관리된다고 가정해보겠습니다.

수 천개 수준에서는 그냥 전체 데이터에 대해 풀스캔으로 처리해도 충분합니다.(중간에 캐시 레이어를 설정할 수도 있는 것이고)

괜히 인덱스를 설정하면, 쓰기 작업이 잦은 데이터에 대해 부가적인 인덱스 관리 비용만 커질 수 있습니다.

 

그래도 쿼리 요구사항이 다양하다면 인덱스를 만드는 것이 불가피할 수 있습니다.

하지만 인덱스는 개념적인 것이고, 단일한 RDB에서 간편하게 만들 수 있도록 지원도 해주는 것이지,

꼭 RDB의 index 기능을 활용할 필요는 없습니다.

별도의 테이블 또는 별도의 DB(아예 다른 DB도 가능)에다가 인덱스를 위한 데이터 구조를 만들고,

쿼리 요구사항을 위한 식별자 조회는 별도의 인덱스 데이터 구조(secondary index를 직접 만든다고 생각하면 됩니다)에서 조회 -> 실제 데이터는 원본 DB에서 조회하는 전략을 취할 수도 있습니다.

인덱스와 원본 데이터를 분리하고, 애플리케이션에서 조인하게 되는 것이라고 봐주시면 되네요.

이러면, 원본 데이터 DB의 인덱스 관리 비용은 별도의 DB로 분산시킬 수 있습니다.

관련해서는 제 강의 중 "분산 데이터 모델링"에서도 가볍게 언급되는 부분이라, 참고 차 말씀 드려봅니다!(꼭 들을 필요는 없습니다)

 

검색 %검색어%의 경우에는 결국엔 full_scan이어서 성능 최적화가 불가능하다.

이것도 말씀하신대로 %검색어% 쿼리는 인덱스 최적화가 불가합니다.

동작 원리를 생각하면 검색어% 쿼리만 인덱스 최적화가 되는 것이고요.

이 부분은 필터링/정렬 등 방식의 인덱싱 방식이 아니라, 검색 엔진의 인덱싱 방식을 참고해보시면 됩니다.

역인덱스(inverted index)라는 방식인데요, "[키워드 목록] -> 찾고자하는 식별자"와 같은 형태로 인덱스가 만들어집니다.

관련해서는 따로 학습해보셔도 좋을 것 같고,

보통 복잡한 검색 기능은 별도의 검색 엔진에다가 데이터를 복제해서 전용으로 검색 DB를 구축하는 것이 일반적이네요!

dltkdcksqkqh님의 프로필 이미지
dltkdcksqkqh
질문자

친절한 답변 감사합니다.

설명해주신 부분들을 바탕으로 추가 학습해보도록 하겠습니다.

많은 도움이 되었습니다.

0

안녕하세요, 인프런 AI 인턴입니다. dltkdcksqkqh님.

복합적인 조회 패턴에서 데이터베이스 성능 최적화를 하는 것은 중요한 과제입니다. 특히, 여러 정렬 조건과 필터, 검색 조건이 함께 사용될 때 효과적으로 처리하기 위해서는 다양한 전략이 필요합니다.

1. 커버링 인덱스 활용

  • 커버링 인덱스는 특정 쿼리의 모든 데이터를 인덱스만으로 충족시킬 수 있도록 구성된 인덱스를 말합니다. 적절히 설계된 커버링 인덱스를 사용하면 쿼리 성능이 향상될 수 있습니다.
  • 하지만, 모든 컬럼에 대해 커버링 인덱스를 사용하는 것은 비효율적일 수 있습니다. 따라서, 사용 빈도가 높고 중요도가 큰 컬럼들에 대해 선택적으로 커버링 인덱스를 적용하는 것이 바람직합니다.

2. 복합 인덱스 적용

  • 여러 컬럼에 대해 조합 인덱스를 생성함으로써 복잡한 조회 시에 성능을 향상시킬 수 있습니다. 인덱스를 설정할 때는 조회 패턴(WHERE 절, JOIN 조건 등)을 고려하여 순서를 결정하는 것이 중요합니다.

3. Full-text 검색 엔진 도입

  • %검색어% 와 같은 패턴 매칭은 인덱스를 타지 않으며, Full Scan의 성능 저하 문제를 유발합니다. 이를 해결하기 위해, Elasticsearch 같은 전문적인 텍스트 검색 엔진의 도입을 고려해볼 수 있습니다. 이러한 솔루션은 대규모 텍스트 검색에서 뛰어난 성능을 발휘합니다.

4. 데이터베이스 파티셔닝 & 샤딩

  • 대규모 데이터셋의 경우, 데이터베이스 파티셔닝이나 샤딩을 통해 데이터 분산을 고려할 수 있습니다. 이렇게 함으로써 각 파티션이나 샤드 별로 부하를 감소시키고, 성능을 최적화할 수 있습니다.

추가 자료 및 참고 링크

유사한 주제에 대한 심화된 예시를 확인하려면 아래의 링크를 참고하실 수 있습니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

dltkdcksqkqh님의 프로필 이미지
dltkdcksqkqh

작성한 질문수

질문하기