Elasticsearch는 빠른 실시간 검색 기능을 제공하기 위해 Apache Lucene을 사용하여 구축된 오픈 소스 분산 기반 검색 및 분석 엔진입니다. 기본적으로 문서 지향적이고 확장 가능하며 스키마가 없는 NoSQL 데이터 저장소입니다. Elasticsearch는 대규모 데이터 세트를 사용하여 대규모로 작동하도록 설계되었습니다. 검색 엔진으로서 여러 노드에 걸쳐 수평으로 확장할 수 있는 빠른 인덱싱 및 검색 기능을 제공합니다. JSON 뻔뻔한 플러그: 클라우드의 실시간 인덱싱 데이터베이스입니다. 검색뿐만 아니라 집계 및 조인에도 최적화된 인덱스를 자동으로 구축하므로 데이터의 출처와 형식에 관계없이 애플리케이션에서 데이터를 빠르고 쉽게 쿼리할 수 있습니다. 하지만 이 게시물에서는 몇 가지 해결 방법을 강조합니다. , Elasticsearch에서 SQL 스타일 조인을 실제로 수행하려는 경우. Rockset은 데이터 관계가 중요한 이유는 무엇입니까? 우리는 데이터 관계를 처리하는 것이 중요한 고도로 연결된 세상에 살고 있습니다. 관계형 데이터베이스는 관계를 잘 처리하지만 끊임없이 변화하는 비즈니스 요구 사항으로 인해 이러한 데이터베이스의 고정된 스키마로 인해 확장성 및 성능 문제가 발생합니다. NoSQL 데이터 저장소의 사용은 기존 데이터 처리 접근 방식과 관련된 여러 가지 문제를 해결할 수 있는 능력으로 인해 점점 더 대중화되고 있습니다. 기업은 데이터를 분석하기 위해 집계, 조인 및 필터링 기능이 필요한 복잡한 데이터 구조를 지속적으로 다루고 있습니다. 비정형 데이터가 폭발적으로 증가함에 따라 데이터 분석 목적으로 다양한 소스의 데이터를 결합해야 하는 사용 사례가 늘어나고 있습니다. 조인은 주로 SQL 개념이지만 NoSQL 세계에서도 똑같이 중요합니다. SQL 스타일 조인은 일류 시민으로서 Elasticsearch에서 지원되지 않습니다. 이 기사에서는 비정규화, 애플리케이션 측 조인, 중첩 문서, 상위-하위 관계와 같은 다양한 기술을 사용하여 Elasticsearch에서 관계를 정의하는 방법에 대해 설명합니다. 또한 각 접근 방식과 관련된 사용 사례와 과제도 살펴봅니다. Elasticsearch에서 관계를 처리하는 방법 Elasticsearch는 관계형 데이터베이스가 아니기 때문에 조인은 SQL 데이터베이스처럼 기본 기능으로 존재하지 않습니다. 스토리지 효율성보다는 검색 효율성에 더 중점을 둡니다. 저장된 데이터는 빠른 검색 사용 사례를 구동하기 위해 사실상 평면화되거나 비정규화됩니다. Elasticsearch에서 관계를 정의하는 방법에는 여러 가지가 있습니다. 사용 사례에 따라 Elasticsearch에서 아래 기술 중 하나를 선택하여 데이터를 모델링할 수 있습니다. 일대일 관계: 객체 매핑 일대다 관계: 중첩 문서 및 상위-하위 모델 다대다 관계: 비정규화 및 애플리케이션 측 조인 일대일 객체 매핑은 간단하므로 여기서는 많이 다루지 않습니다. 이 블로그의 나머지 부분에서는 다른 두 가지 시나리오를 더 자세히 다룰 것입니다. Elasticsearch에서 데이터 모델 관리 Elasticsearch의 데이터 관리에는 네 가지 일반적인 접근 방식이 있습니다. 비정규화 애플리케이션 측 조인 중첩된 객체 부모-자식 관계 비정규화 비정규화는 쿼리 시 데이터 세트 조인이 필요하지 않기 때문에 Elasticsearch에서 최고의 쿼리 검색 성능을 제공합니다. 각 문서는 독립적이며 필요한 모든 데이터를 포함하므로 비용이 많이 드는 조인 작업이 필요하지 않습니다. 비정규화를 사용하면 인덱싱 시 데이터가 평면화된 구조로 저장됩니다. 이로 인해 문서 크기가 늘어나고 각 문서에 중복된 데이터가 저장됩니다. 디스크 공간은 값비싼 상품이 아니므로 걱정할 필요가 거의 없습니다. 비정규화 사용 사례 분산 시스템으로 작업하는 동안 네트워크를 통해 데이터 세트를 결합해야 하면 상당한 지연 시간이 발생할 수 있습니다. 데이터를 비정규화하면 이러한 비용이 많이 드는 조인 작업을 피할 수 있습니다. 다대다 관계는 데이터 평면화를 통해 처리할 수 있습니다. 데이터 비정규화 문제 데이터를 병합된 문서로 복제하려면 추가 저장 공간이 필요합니다. 평면화된 구조에서 데이터를 관리하면 본질적으로 관계형인 데이터 세트에 대한 추가 오버헤드가 발생합니다. 프로그래밍 관점에서 비정규화에는 추가적인 엔지니어링 오버헤드가 필요합니다. 여러 관계형 테이블에 저장된 데이터를 평면화하고 이를 Elasticsearch의 단일 개체에 매핑하려면 추가 코드를 작성해야 합니다. 데이터가 자주 변경되는 경우 데이터를 비정규화하는 것은 좋은 생각이 아닙니다. 이러한 경우 비정규화는 데이터의 하위 집합이 변경될 때 모든 문서를 업데이트해야 하므로 피해야 합니다. 더 많은 데이터가 인덱싱되므로 인덱싱 작업은 평면화된 데이터 세트의 경우 더 오래 걸립니다. 데이터가 자주 변경되는 경우 이는 인덱싱 속도가 더 높아 클러스터 성능 문제가 발생할 수 있음을 의미합니다. 애플리케이션 측 조인 문서 간 관계를 유지해야 하는 경우 애플리케이션 측 조인을 사용할 수 있습니다. 데이터는 별도의 인덱스에 저장되며 쿼리 시간 동안 애플리케이션 측에서 조인 작업을 수행할 수 있습니다. 그러나 이는 문서를 결합하기 위해 애플리케이션에서 검색 시 추가 쿼리를 실행하는 것을 수반합니다. 애플리케이션 측 조인 사용 사례 애플리케이션 측 조인은 데이터가 정규화된 상태로 유지되도록 보장합니다. 수정은 한 곳에서 이루어지며 문서를 지속적으로 업데이트할 필요가 없습니다. 이 접근 방식을 사용하면 데이터 중복이 최소화됩니다. 이 방법은 문서 수가 적고 데이터 변경 빈도가 낮을 때 효과적입니다. 애플리케이션 측 조인의 과제 애플리케이션은 검색 시 문서를 결합하기 위해 여러 쿼리를 실행해야 합니다. 데이터 세트에 소비자가 많은 경우 동일한 쿼리 세트를 여러 번 실행해야 하므로 성능 문제가 발생할 수 있습니다. 따라서 이 접근 방식은 Elasticsearch의 실제 기능을 활용하지 않습니다. 이 접근 방식은 구현 수준에서 복잡성을 초래합니다. 문서 간의 관계를 설정하기 위해 조인 작업을 구현하려면 애플리케이션 수준에서 추가 코드를 작성해야 합니다. 중첩된 객체 배열에 있는 각 객체의 관계를 유지해야 하는 경우 중첩 접근 방식을 사용할 수 있습니다. 중첩된 문서는 내부적으로 별도의 Lucene 문서로 저장되며 쿼리 시 결합될 수 있습니다. 이는 여러 Lucene 문서가 단일 블록에 저장되는 인덱스 시간 조인입니다. 애플리케이션 관점에서 보면 블록은 단일 Elasticsearch 문서처럼 보입니다. 따라서 모든 데이터가 동일한 개체에 상주하므로 쿼리가 상대적으로 더 빠릅니다. 중첩된 문서는 일대다 관계를 처리합니다. 중첩된 문서의 사용 사례 문서에 개체 배열이 포함된 경우 중첩된 문서를 만드는 것이 좋습니다. 아래 그림 1은 Elasticsearch의 중첩 유형을 사용하여 객체 배열을 별도의 Lucene 문서로 내부적으로 인덱싱하는 방법을 보여줍니다. Lucene에는 내부 개체에 대한 개념이 없으므로 Elasticsearch가 내부적으로 원본 문서를 평면화된 다중 값 필드로 변환하는 방법을 보는 것은 흥미롭습니다. 중첩 쿼리를 사용하면 개체 간 일치를 수행하지 않으므로 예기치 않은 일치 결과가 방지된다는 장점이 있습니다. 객체 경계를 인식하므로 검색이 더 정확해집니다. 그림 1: 중첩 접근 방식을 사용하여 Elasticsearch에서 별도의 Lucene 문서로 내부적으로 인덱싱된 개체 배열 중첩된 객체에 대한 과제 중첩 개체를 추가/업데이트/삭제하려면 루트 개체와 해당 중첩 개체를 완전히 다시 인덱싱해야 합니다. 즉, 하위 레코드를 업데이트하면 전체 문서가 다시 색인화됩니다. 중첩된 문서에는 직접 액세스할 수 없습니다. 관련 루트 문서를 통해서만 액세스할 수 있습니다. 검색 요청은 검색 쿼리와 일치하는 중첩 문서만 반환하는 대신 전체 문서를 반환합니다. 데이터 세트가 자주 변경되는 경우 중첩된 문서를 사용하면 많은 업데이트가 발생합니다. 부모-자식 관계 상위-하위 관계는 관계가 있는 개체를 개별 문서(상위 및 하위)로 완전히 분리하기 위해 활용합니다. 이를 통해 별도로 업데이트할 수 있는 별도의 Elasticsearch 문서에 관계형 구조로 문서를 저장할 수 있습니다. 조인 데이터 유형을 문서를 자주 업데이트해야 할 경우 부모-자식 관계가 도움이 됩니다. 따라서 이 접근 방식은 데이터가 자주 변경되는 시나리오에 이상적입니다. 기본적으로 기본 문서를 상위 문서와 하위 문서가 포함된 여러 문서로 분리합니다. 이를 통해 상위 문서와 하위 문서를 서로 독립적으로 색인화/업데이트/삭제할 수 있습니다. 상위 및 하위 문서에서 검색 인덱싱 및 검색 중에 Elasticsearch 성능을 최적화하려면 문서 크기가 크지 않은지 확인하는 것이 일반적인 권장 사항입니다. 상위-하위 모델을 활용하여 문서를 별도의 문서로 나눌 수 있습니다. 그러나 이를 구현하는 데에는 몇 가지 과제가 있습니다. 상위 및 하위 문서는 쿼리 시간 동안 결합이 메모리 내에서 효율적으로 이루어지도록 동일한 분할로 라우팅되어야 합니다. 상위 ID는 하위 문서의 라우팅 값으로 사용해야 합니다. 필드는 Elasticsearch에 상위 문서의 ID와 유형을 제공하며, 이를 통해 내부적으로 하위 문서를 상위 문서와 동일한 샤드로 라우팅할 수 있습니다. _parent Elasticsearch를 사용하면 복잡한 JSON 개체에서 검색할 수 있습니다. 그러나 이를 효율적으로 쿼리하려면 데이터 구조에 대한 철저한 이해가 필요합니다. 상위-하위 모델은 여러 필터를 활용하여 검색 기능을 단순화합니다. 쿼리 has_child 쿼리와 일치하는 하위 문서가 있는 상위 문서를 반환합니다. 쿼리 has_parent 상위를 승인하고 연관된 상위가 일치하는 하위 문서를 반환합니다. 쿼리 inner_hits 쿼리에서 관련 하위 정보를 가져옵니다. has_child 그림 2는 일대다 관계를 보여주기 위해 부모-자식 모델을 사용하는 방법을 보여줍니다. 상위 문서에 영향을 주지 않고 하위 문서를 추가/제거/업데이트할 수 있습니다. 하위 항목을 다시 색인화하지 않고도 업데이트할 수 있는 상위 문서의 경우에도 마찬가지입니다. 그림 2: 일대다 관계에 대한 상위-하위 모델 부모-자녀 관계의 어려움 쿼리는 조인 작업으로 인해 비용이 더 많이 들고 메모리 집약적입니다. 부모-자식 구성은 쿼리 시 결합해야 하는 별도의 문서이므로 오버헤드가 있습니다. 상위와 모든 하위가 동일한 샤드에 존재하는지 확인해야 합니다. 상위-하위 관계로 문서를 저장하면 구현이 복잡해집니다. 결론 올바른 Elasticsearch 설계를 선택하는 것은 애플리케이션 성능과 유지 관리에 매우 중요합니다. Elasticsearch에서 데이터 모델을 디자인할 때 여기에서 논의된 네 가지 모델링 방법 각각의 다양한 장단점을 알아두는 것이 중요합니다. 데이터 모델링 이 기사에서는 중첩된 객체와 상위-하위 관계가 어떻게 Elasticsearch에서 SQL과 유사한 조인 작업을 가능하게 하는지 살펴보았습니다. 또한 애플리케이션 측 조인과의 관계를 처리하기 위해 애플리케이션에 사용자 정의 논리를 구현할 수도 있습니다. Elasticsearch에서 여러 데이터 세트를 조인해야 하는 사용 사례의 경우, 두 데이터 세트를 모두 수집하고 Elasticsearch 인덱스에 로드하여 성능 쿼리를 활성화할 수 있습니다. 기본적으로 Elasticsearch에는 SQL 데이터베이스처럼 조인이 없습니다. 문서에서 관계를 설정하기 위한 잠재적인 해결 방법이 있지만 이러한 각 접근 방식이 제시하는 문제를 인식하는 것이 중요합니다. Rockset에서 기본 SQL 조인 사용 실시간 분석을 위해 여러 데이터 세트를 결합해야 하는 경우 기본 SQL 조인을 제공하는 데이터베이스가 이 사용 사례를 더 잘 처리할 수 있습니다. Elasticsearch와 마찬가지로 Rockset은 데이터베이스, 이벤트 스트림 및 데이터 레이크의 데이터에 대한 인덱싱 계층으로 사용되어 이러한 소스에서 스키마 없는 수집을 허용합니다. Elasticsearch와 달리 Rockset은 조인을 포함한 기능을 제공하므로 데이터 사용 방법에 있어 더 큰 유연성을 제공합니다. 모든 기능을 갖춘 SQL로 쿼리하는 게시되었습니다. 여기에도