엔지니어링

Elasticsearch의 숫자 및 날짜 범위: 벽 안의 또다른 벽돌

이 게시물이 마음이 드시나요? 숫자와 Elasticsearch를 좋아하시나요? 제가 직접 Elastic{ON}에서 참가자 여러분을 만나 질문에 답해드릴 예정입니다. 저희 행사에 참가하세요. 행사장에서 뵙길 바랍니다.

새로운 일정이 잡혔을 때 이 일정과 충돌하는 모든 이벤트를 빠르게 찾을 수 있도록 캘린더를 색인할 수 있다고 상상해 보십시오. 또는 특정 시간대에 방송되는 모든 프로그램, 영화, 스포츠 등을 찾기 위한 전 세계 TV 채널 가이드를 작성한다고 상상해 보십시오. 좀 더 미래 세계적인 것을 원하시나요? 잠재적인 악성 활동을 신속하게 식별, 분류 및 진단하기 위해 지금까지 알려진 모든 암세포의 스펙트럼 시그니처 에 대한 카탈로그를 작성한다고 상상해 보십시오.

이산(discrete) 에서 연속(continuous) 형식으로

최근까지 이런 사례들은 Elasticsearch의 이산형 숫자(numeric)날짜(date) 필드를 사용하였기에 대규모의 처리가 극히 어렵거나 불가능했습니다. 범위(range) 쿼리를 이산 포인트로 실행하는 것이 일반적인 기능으로 널리 사용되었지만, 색인 및 검색을 연속 범위(continuous ranges)로 하게 될 경우 훨씬 더 유용할 것이라는 것이 명백해졌습니다. Apache Lucene 의 최근 발전 덕분에 이러한 바람이 Elasticsearch에서 실현되었습니다.

Elasticsearch에 새롭게 포함되는 Numeric 및 Date Range 필드 형식

Elasticsearch 5.2 릴리스에는 다음과 같은 새로운 Range 필드 형식이 포함됩니다.

  • integer_range
  • float_range
  • long_range
  • double_range
  • date_range

    이러한 새로운 range 데이터 형식의 매핑 정의는 이산형 Numeric 및 Date와 동일한 방식으로 작동합니다. integer 및 date range가 모두 포함된 도큐먼트 유형("컨퍼런스 conference"라고 함)에 대한 매핑 정의 예는 다음과 같습니다.

    PUT events/
    {
      "mappings" : {
        "conference" : {
          "properties" : {
            "expected_attendees" : {
              "type" : "integer_range"
            },
            "time" : {
              "type" : "date_range",
              "format" : "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" 
            }
          }
        }
      }
    }
    

    위의 매핑을 사용하여 문서를 색인하는 것은 Numeric 또는 Date Range 쿼리에서 range 필드를 명시하는 것처럼 간편합니다. Date Range 쿼리와 마찬가지로 Date Range 필드를 색인할 때도 동일한 Date Math 형식 정의를 사용합니다. 다음 예에서는 integer_range 및 date_range 필드 형식으로 문서를 색인하는 것을 보여줍니다.

    PUT events/conference/1
    {
      "title" : "Pink Floyd / Wizard of Oz Halloween Trip",
      "expected_attendees" : {
        "gte" : 100000,
        "lt" : 200001
      },
      "time" : {
        "gte" : "2015-10-31 12:00",
        "lt" : "2015-11-01"
      }
    }
    

    Numeric 및 Date Range 필드는 이전과 동일한 Range Query DSL 문법을 사용하며, 추가적인 매개 변수들의 사용이 가능합니다. 사용자는 이 매개 변수를 통해 원하는 Range 쿼리 을 사용할 수 있습니다. 매개 변수 들 INTERSECTS (기본값), CONTAINS 또는 WITHIN 중 하나로 정의되며 다른 Boolean 쿼리와 결합하여 원하는 결과를 다양하게 얻을 수 있습니다(예: DISJOINT). 다음 예에서는 이벤트 인덱스에 대한 WITHIN 쿼리를 보여줍니다.

    GET events/_search
    {
      "query" : {
        "range" : {
          "time" : {
            "gte" : "2015-10-01",
            "lte" : "2015-12-31",
            "relation" : "within"
          }
        }
      }
    }
    

    이산형 numeric 및 date 필드와 마찬가지로 새로운 range도 현재 단일 차원으로만 사용이 가능합니다. 하지만 앞으로 이 제한을 없애고 앞으로는 8차원과 4차원을 처리하도록 확장할 예정입니다.

    Lucene 구현

    2016년 10월 18일, 저희는 Apache Lucene에서 Numeric Range 필터의 발전을 설명하는 블로그 포스트를 게시했습니다. 숫자 검색 엔진으로서 Lucene의 발전 과정에 대한 이 역사적 기록은 숫자 색인 및 검색이 Bkd-Tree 데이터 구조를 통해 최고 정점에 이르게 되는 기술적 진보 과정을 자세히 설명합니다. 텍스트를 위해 특별히 설계 및 조정된 구조를 사용해서 숫자 데이터를 표현하는 대신, Bkd 구현에서는 이산 숫자점의 색인만을 위해 설계된 최초의 유연한 트리 구조를 도입했습니다. 그에 따라 이제 이러한 이산 숫자점을 Elasticsearch에서 numeric range query DSL 문법을 사용하여 검색할 수 있게 되었습니다. k차원 트리 (k-d tree), 의 이론과 개념을 바탕으로 구성된 새로운 점(Point) 코덱 형식은 고급 과학 또는 데이터 분석 사례에 대한 다차원 기능 지원을 제공할 수 있는 길을 닦아놓았을 뿐만 아니라, range 필드를 Lucene과 궁극적으로 Elasticsearch에 활용하는 데 필요한 기초가 되는 클래스를 제공합니다.

    색인(Indexing)

    해결 방법은 의외로 간단했습니다. 각 차원에 대해 차원 숫자 범위를 2차원 점으로 표현하고, 이때 인코딩을 최소값 d(각 차원별) 배열과 최대값 D 배열 순으로 저장합니다. 이것은 8 차원으로 제한하는 Bkd 구조에서 Lucene이 제공 한 numeric range 필드는 최대 4 차원 범위의 색인까지만 지원한다는 것을 의미합니다. 아래 그림은 Lucene의 차원 범위 인코딩을 간략하게 보여줍니다.

    Lucene's Dimensional Range Encoding

    기본적으로 Lucene에게 1차원 범위는 2차원 점 처럼 보입니다. 그런 다음 이 인코딩을 Bkd 인덱서로 전달하여, d*2차원 점의 계층 트리를 구성합니다. 여기서 d는 범위 차원(위 그림에서는 4)입니다.

    검색(Searching)

    차원 범위에 대한 검색 구현은 사용자가 제시한 검색 범위(대상)와 색인된 범위(또는 트리의 각 레벨의 최소 경계 범위) 사이의 공간 관계를 정의하고 계산하는 하나의 주요한 단계로 이루어집니다. 이는 각 차원의 범위 관계를 평가하는 차원 범위 비교 연산자를 구현하여 수행합니다. 비교 연산자, 즉, Lucene numeric range 쿼리에서 구현되는 공간 관계는 INTERSECTS, CONTAINS, WITHIN 등입니다. DISJOINT 쿼리는 boolean 쿼리의 MUST_NOT 에 INTERSECTS 쿼리를 포함하여 구현됩니다. 다중 값을 가진 필드의 경우, 모든 값이 서로 겹치지 않는 경우에만 도큐먼트가 DISJOINT로 간주됩니다. CROSSES 관계는 현재 개발 중이며 이후에 향상된 기능으로 제공될 예정입니다. 다음 그림은 두 개의 간단한 1차원 범위 사이의 계산된 관계를 보여줍니다.

    Range Relations

    이 예는 속이 빈 점이 지정된 값을 포함하지 않는 범위를 나타내는 규칙을 따릅니다. 분홍색 범위는 대상(쿼리)을 나타내고 청록색 범위는 색인된 범위를 나타냅니다.

    한번 사용 해 보십시오...

    저희는 Numeric 및 Date range 형식의 색인 및 검색이 사용자들의 사용 사례에 독특하고 창의적으로 사용되는 것들을 보는 것이 즐겁고 기쁘게 생각합니다. 언제나처럼 Elasticsearch 깃헙(GitHub) 페이지에 피드백, 제안 및 기고해 주시길 바라며 이 새 필드 형식들을 편리하게 이용하시길 바랍니다!

    이제 시간이 다 되어서 노래가 끝났네요... 즐기시길 바랍니다!