이 영역을 누르면 첫 페이지로 이동
천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

페이지 맨 위로 올라가기

천천히 꾸준히 조용히

천천히 꾸준히 조용히.. i3months 블로그

[Elasticsearch] 인덱스 재구성 및 최적화

  • 2025.11.13 15:44
  • 💡 솔루션
반응형

 

 

 

1. 단일 인덱스와 다중 인덱스 비교 

 

<단일 인덱스 구조가 더 효과적인 경우>

- 데이터 스키마 필드 구조가 거의 같음 

- 여러 도메인을 통합해서 검색해야 함 

- 크기가 수백 GB 이하임 

- 특정 필드를 기준으로 검색을 최적화 할 수 있어야 함

- 데이터가 자주 업데이트 됨 

- 모든 사용자가 같은 방식으로 검색 

 

<다중 인덱스 구조가 더 효과적인 경우>

- 데이터 스키마 필드 구조가 다름 

- 도메인별로 분리해서 검색해야 함 

- 크기가 매우 크거나 데이터 증가 속도가 매우 빠름 

- 특정 데이터만 업데이트 해야 함 

- 사용자별로 데이터가 다름 

 

다중 인덱스를 사용한다고 해서 무조건 느린 건 아니다. Elasticsearch의 검색 성능은 쿼리가 hit 하는 shard의 총 개수에 의해 결정됨. 

그러니까.. 검색 패턴에 따라서 shard의 수를 최소화하고 데이터의 성격에 맞춰서 인덱스를 분리해 줘야 함.

 

 

2. 현재 시스템에서의 문제점

 

Elasticsearch를 RDB처럼 정규화해서 모든 연관 정보를 별개의 인덱스로 분리하기에 성능 저하가 심하다.

정규화된 아키텍처에서는 상세 페이지 조회 시 모든 관련 인덱스에 multi_search 요청을 보내 강제로 JOIN을 수행함.

 

검색용 데이터와 상세 페이지용 데이터에서 중복된 내용을 제거해 줘야 함.

스토리지도 낭비되고 시스템 간 동기화를 지속적으로 해 줘야 함.

 

인덱스의 스키마가 동일하지만, 검색 시 두 인덱스를 합쳐서 통합 검색을 수행하고 있음.

Elasticsearch 에서의 Alias 기능을 사용해 단일 인덱스처럼 사용할 수 있음.

 

 

3. 인덱스 재구성 및 최적화 

 

JOIN 수행 시점을 인덱스 타임으로 이전하자.

쿼리 할 때 multi_search 로 여러 인덱스를 JOIN 하기에 성능 저하가 너무 심하다.

RDB에서 Elasticsearch로 인덱싱 할 때 미리 JOIN 해두는 방식을 사용함.

 

node_detail 

multi_search 병목을 제거하기 위한 핵심 인덱스.

기존에 분산되어 있던 상세 정보를 NODE_ID 기준으로 비정규화해서 단일 JSON 문서로 구성함.

 

JSON 구조가 복잡해지긴 한다. 

그래도 인덱스의 목적이 단순 조회니까 이렇게 설정함 

 

 

node_info_in / node_info_out 

실제 검색 요청을 처리하는 경량화된 인덱스.

node_detail 에 있는 불필요한 상세 정보들을 모두 제거해서 크기를 최소화하고 검색 성능을 끌어올림.

 

in(내부) out(외부) 를 따로 구성함. 내부 데이터와 외부 데이터의 업데이트 주기가 다르기 때문.. 

실제 검색 할 때는 인덱스의 존재를 알 필요가 없음. Alias를 생성해서 두 인덱스를 묶어두고, 단일 엔드포인트처럼 사용함.

 

autr_info

저자 정보 고도화를 위해 분리된 인덱스.

저자와 해당 저자에 포함된 논문들의 NODE_ID를 저장한다.

 

현재 저자정보 데이터는 PK 값이 명확하지 않음. 중복된 사용자가 많다.

node_info 인덱스에 autr_info 를 함께 비정규화해서 포함시키면 검색 결과가 오염됨.

그러니 별도 인덱스를 둬서 격리시키고 메인 논문 검색은 저자 정보와 무관하게 검색될 수 있도록 설정함. 

 

 

 

4. 관련 고려사항 

 

1. 결과 내 재검색 기능 

 

검색 결과 페이지 좌측에는 다양한 집계 항목이 있음. (이용형태, 발행년도 등..)

 

이걸 누르면 결과 내 재검색 필터로 동작해야 하는데.. 

집계용 필드를 따로 별도의 인덱스로 분리해볼까 했지만.. 힘들어보임.

 

node_info 인덱스와 집계 인덱스를 따로 분리했다고 하자. 그러면 결과 내 검색 할 때 또 JOIN 해야함;; 

지금처럼 집계 정보가 node_info 문서 안에서 비정규화 되어 있으니 효율적으로 처리할 수 있다. 

 

 

GET /node_info_all/_search
{
  "query": {
    "bool": {
      "must": { "match": { "title": "Elasticsearch" } },
      "filter": { "term": { "publication_year": 2023 } }
    }
  },
  "aggs": {
    "publication_year_counts": {
      "terms": { "field": "publication_year" }
    }
	// .....
  }
}

 

 

이런식으로..

그러니 지금 구조가 가장 깔끔하다. 

 

 

2. search_after 쿼리와 Deep Pagination

 

Elasticsearch 7.x 부터 index.max_result_window의 기본값이 10,000건으로 제한됨.

(https://wefree.tistory.com/21)

찾아보니 from / size 방식의 근본적인 비용 때문에 도입된 안전장치 라고 함.

(https://medium.com/@imadsaddik/16-deep-pagination-in-elasticsearch-search-after-vs-from-size-11fb39131b63)

 

10,000 건 이상의 결과를 탐색하려면 어쩔수없이 search_after 파라미터를 사용해야 한다.

// page 1
GET /node_info_all/_search
{
  "size": 10,
  "query": { "match": { "title": "Elasticsearch" } },
  "sort": [
    { "publication_year": "desc" },
    { "_score": "desc" },
    { "_id": "asc" }
  ]
}

// page 1의 마지막 문서에서 "sort" 값을 추출: [2020, 15.34, "doc_id_1"]

// page 2
GET /node_info_all/_search
{
  "size": 10,
  "query": { "match": { "title": "Elasticsearch" } },
  "sort": [
    { "publication_year": "desc" },
    { "_score": "desc" },
    { "_id": "asc" }
  ],
  "search_after": [2023, 15.34, "doc_id_1"]
}

 

 

 

 

 

 

 

반응형
저작자표시 (새창열림)

'💡 솔루션' 카테고리의 다른 글

[GCP] AWS RDS to GCP Cloud SQL 과 SSL 설정  (0) 2026.01.12
[SQL Server] 고비용 쿼리 튜닝  (0) 2025.11.29
localhost 브라우저에서 쿠키 제대로 받기  (0) 2025.06.25
[SQL Server] 암호화 된 View 다루기  (1) 2025.01.03
[MySQL] WITH RECURSIVE 계층 쿼리  (0) 2024.12.13

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [GCP] AWS RDS to GCP Cloud SQL 과 SSL 설정

    [GCP] AWS RDS to GCP Cloud SQL 과 SSL 설정

    2026.01.12
  • [SQL Server] 고비용 쿼리 튜닝

    [SQL Server] 고비용 쿼리 튜닝

    2025.11.29
  • localhost 브라우저에서 쿠키 제대로 받기

    localhost 브라우저에서 쿠키 제대로 받기

    2025.06.25
  • [SQL Server] 암호화 된 View 다루기

    [SQL Server] 암호화 된 View 다루기

    2025.01.03
다른 글 더 둘러보기

정보

천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

  • 천천히 꾸준히 조용히의 첫 페이지로 이동

검색

방문자

  • 전체 방문자
  • 오늘
  • 어제

카테고리

  • 분류 전체보기 (675) N
    • Algorithm (205)
      • Data Structure (5)
      • Theory && Tip (33)
      • Baekjoon (166)
      • ALGOSPOT (1)
    • Spring (123)
      • Spring (28)
      • Spring Web MVC (20)
      • Spring Database (14)
      • Spring Boot (6)
      • Spring 3.1 (11)
      • Spring Batch (6)
      • Spring Security (16)
      • JPA (12)
      • Spring Data JPA (5)
      • QueryDSL (4)
      • eGovFramework (1)
    • Programming Language (74)
      • C (25)
      • C++ (12)
      • Java (19)
      • JavaScript (15)
      • Python (1)
      • PHP (2)
    • Computer Science (142)
      • Machine Learning (38)
      • Operating System (18)
      • Computer Network (28)
      • System Programming (22)
      • Universial Programming Lang.. (8)
      • Computer Architecture (4)
      • Compiler Design (11)
      • Computer Security (13)
    • Database (21)
      • Database (7)
      • MySQL (3)
      • Oracle (3)
      • Redis (5)
      • Elasticsearch (3)
    • DevOps (20)
      • Docker && Kubernetes (8)
      • Jenkins (4)
      • Amazon Web Service (8)
    • Mobile (28)
      • Android (21)
      • Flutter (7)
    • 💡 솔루션 (17)
    • 👥 모각코 (8)
    • 💬 기록 (7) N
    • 📚 공부 (5)
    • -------------- (25)

최근 글

나의 외부 링크

메뉴

  • 홈
반응형

정보

i3months의 천천히 꾸준히 조용히

천천히 꾸준히 조용히

i3months

블로그 구독하기

  • 구독하기
  • RSS 피드

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. Copyright © i3months.

티스토리툴바