Elasticsearch에서 관계 관리
7554 단어 elasticsearch
현실 세계에서 데이터는 매우 적고 간단하며 통상적인 상황은 모두 혼란스러운 교차 관계를 가지고 있다.
우리는 어떻게 Elasticsearch에서 문서(데이터) 간의 관계를 표현해야 합니까?여기에는 문서 간의 관계에 대한 지원을 제공할 수 있는 메커니즘이 있다.이러한 메커니즘은 각자의 우세와 열세를 가지고 있으므로 반드시 서로 다른 장면에 따라 적절하게 사용해야 한다.
Inner Objects
가장 간단한 메커니즘은 내부 대상이라고 불린다.다음은 상위 객체에 포함된 JSON 객체입니다.
{
"name":"Zach",
"car":{
"make":"Saturn",
"model":"SL"
}
}
간단하죠?
car
필드는 make
및 model
두 속성을 가진 내부 객체입니다.루트 대상과 내부 대상 간에 일대일 관계에 속할 때 이런 내부 대상의 매핑 관계는 효과적이다.예를 들어 사람마다 최대 1개car
가 함유되어 있다.그러나
Zach
두 개car
를 가지고 있고 Bob
한 개car
만 있을 때는?{
"name" : "Zach",
"car" : [
{
"make" : "Saturn",
"model" : "SL"
},
{
"make" : "Subaru",
"model" : "Imprezza"
}
]
}
{
"name" : "Bob",
"car" : [
{
"make" : "Saturn",
"model" : "Imprezza"
}
]
}
Saturn사가 Imprezza형 자동차를 생산한 적이 없다는 문제를 무시하고 우리가 ES에서 검색을 시도할 때 어떤 일이 일어날지 고려해 보십시오.Bob만 소유하고 있으므로 다음과 같은 질의를 작성할 수 있습니다.
query: car.make=Saturn AND car.model=Imprezza
이게 맞나?좋아, 이런 조회 결과는 결코 우리가 원하는 대로 되지 않을 거야.만약 이 조회 문장을 실행한다면, 우리는 모든 두 개의 문서를 얻을 것이다.이것은 Elasticsearch가 내부에서 내부 대상을 하나의 대상으로 낮추었기 때문이다.따라서
Saturn Imprezza
이 문서는 실제로 다음과 같습니다.{
"name" : "Zach",
"car.make" : ["Saturn", "Subaru"]
"car.model" : ["SL", "Imprezza"]
}
이것은 왜 상술한 조회가 그런 결과를 되돌려 주는지 설명한다.ELasticsearch는 근본적으로 납작하게 처리되기 때문에 문서는 내부에서 납작한 필드로 간주됩니다.
Nested
내부 대상의 또 다른 선택으로 Elasticsearch는 플러그인 유형의 개념을 제공했다.중첩된 문서는 문서 차원과 내부 대상은 같지만 내부 대상에 없는 기능을 제공합니다.
중첩된 문서의 예는 다음과 같습니다.
{
"name" : "Zach",
"car" : [
{
"make" : "Saturn",
"model" : "SL"
},
{
"make" : "Subaru",
"model" : "Imprezza"
}
]
}
내포된 유형은 맵 차원에서 명시적으로 선언해야 합니다(내부 객체와 달리 자동으로 감지할 수 있음).
{
"person":{
"properties":{
"name" : {
"type" : "string"
},
"car":{
"type" : "nested"
}
}
}
}
Inner Objects의 문제는 모든 중첩된 JSON 객체가 문서의 개별 구성 요소로 간주되지 않는다는 것입니다.반대로 다른 Inner Objects와 통합되어 같은 속성 이름을 공유합니다.
이 문제는 Nested 문서에 나타나지 않습니다.모든 Nested 문서는 독립성을 유지하기 때문에 의외의 문제가 발생하지 않도록 사용할 수 있습니다.
Elasticsearch는 근본적으로 여전히 납작하지만, 내부적으로 Nested 관계를 관리하여 끼워 넣는 차원을 나타낼 수 있다.우리가 Nested 문서를 만들 때, Elasticsearch는 실제로 두 개의 독립된 문서 (루트 대상과 중첩 대상) 를 추가한 다음 내부적으로 연결합니다.상기 두 문서는 모두 같은 Shard의 같은 Lucene 블록에 저장되어 읽기 성능이 여전히 매우 빠르다.
이런 안배도 동시에 약간의 폐단을 가져왔다.가장 뚜렷한 것은 우리가 특수한 플러그인 조회를 통해서만 플러그인 문서에 접근할 수 있다는 것이다.또 다른 문제는 우리가 문서의 루트 대상이나 하위 대상에 대한 업데이트 작업을 시도할 때 나타날 것이다.
Nested 문서는 같은 Lucene 블록에 저장되고, Lucene는 단락에 무작위 쓰기를 허용하지 않기 때문에, Nested 문서의 한 필드에 대한 鞥 업데이트 작업은 전체 문서의 인덱스를 재구성할 수 있습니다.
색인 재구성 대상은 수정되지 않았더라도 루트와 중첩된 하위 대상을 포함합니다.내부적으로, Elasticsearch는 문서를 삭제, 업데이트 필드로 표시하고, 문서의 모든 내용을 색인 값의 새로운 Lucene 블록으로 재구성합니다.Nested 문서 데이터가 자주 업데이트되면 인덱스 재구성으로 인한 성능 소모를 무시할 수 없습니다.
또한 Nested 문서 간에 상호 참조를 사용할 수 없습니다.하나의 Nested 객체의 속성은 다른 Nested 객체에 대해 보이지 않습니다.예를 들어 우리는
Zach
과 car.make=Saturn AND car.model=Imprezza
을 동시에 필터 조건으로 조회할 수 없습니다.실행 가능한 방법은 A.name
를 사용하는 것이다. 그러면 중첩된 문서를 루트로 효율적으로 복사할 수 있지만, 이렇게 되면 문제는 다시 Inner Objects의 상황으로 돌아간다.Parent/Child
Elasticsearch가 제공하는 마지막 방법은 Parent/Child 유형을 사용하는 것입니다.이런 모델은 Nested 플러그인에 비해 더욱 느슨한 결합에 속하고 우리에게 더욱 강력한 조회 방식을 제공한다.예를 들어 보자. 이 예에서 한 사람은 여러 가정을 가지고 있다.부모 요소에는 일반적으로 다음과 같은 매핑이 있습니다.
{
"mappings":{
"person":{
"name":{
"type":"string"
}
}
}
}
하위 원소는 부모 원소 외에 자신의 맵핑이 있고 특수한
B.age
속성 집합을 함유하고 있다{
"homes":{
"_parent":{
"type" : "person"
},
"state" : {
"type" : "string"
}
}
}
include_in_root
필드는 Elasticsearch에 _parent
유형 문서가 _parent
유형의 자체 천둥임을 설명합니다.우리는 문서에 이 유형의 데이터를 매우 쉽게 추가할 수 있다.일반적으로 상위 유형 문서를 추가할 수 있습니다.$ curl -XPUT localhost:9200/test/person/zach/ -d'
{
"name" : "Zach"
}
하위 유형 문서를 추가하는 것은 일반적인 것과 약간 다릅니다. 요청 매개 변수에서 이 하위 문서가 속하는 상위 문서를 지정해야 합니다(이 예에서는
Employers
. 이 값은 위에서 상위 문서를 추가할 때 지정한 문서 ID입니다.$ curl -XPOST localhost:9200/homes?parent=zach -d'
{
"state" : "Ohio"
}
$ curl -XPOST localhost:9200/test/homes?parent=zach -d'
{
"state" : "South Carolina"
}
위의 두 문서는 현재
Person
부모 문서와 연결되어 있습니다. 이로써 다음과 같은 조회를 사용할 수 있습니다.Nested의 가장 큰 문제는 그 저장에 있다. 같은 요소의 모든 내용은 같은 Lucene 블록에 저장된다.Parent/Child 방식은 양자를 분리하여 느슨하게 결합시켜 이 제한을 제거합니다.이런 방식은 이익도 있고 폐단도 있다.느슨한 결합 방식은 부모 문서나 다른 하위 문서에 영향을 주지 않기 때문에 부모 문서를 자유롭게 업데이트하거나 삭제할 수 있습니다.
Parent/Child의 단점은 표현 성능이 Nested보다 약간 떨어진다는 것이다.하위 문서는 상위 문서와 같은Shard로 배치되기 때문에 슬라이스 수준의 캐시와 메모리 필터 덕분입니다.그러나 같은 Lucene 블록에 놓여 있지 않기 때문에 Nested 방식에 비해 Parent/Child 방식은 여전히 느리다.이 밖에 이런 방식은 일정한 메모리 부하를 증가시킬 수 있다. 왜냐하면 Elasticsearch는 메모리에 관리 관계의'join table'를 저장해야 하기 때문이다.
마지막으로, 우리는 정렬과 평점 계산이 상대적으로 어렵다는 것을 발견할 것이다.예를 들어 필터링 조건과 일치하는 문서가 무엇인지 알기 어렵고 부모 문서가 일치하는 문서만 얻을 수 있습니다.어떤 상황에서 이 문제는 상당히 까다로울 것이다.
역규범화
때때로 가장 좋은 방법은 적당한 때에 간단하게 데이터의 역규범화를 하는 것이다.Elasticsearch는 특정 상황에서 효과적인 관계 구조 지원을 제공했지만 이것은 우리가 유사한 관계형 데이터베이스 관리 시스템이 제공하는 강한 관계 특성을 사용할 수 있다는 것을 의미하지는 않는다.
Elasticsearch는 본질적으로 납작한 데이터 구조이기 때문에 관계형 데이터를 사용하려고 시도하는 것은 위험하다.일부 상황에서 데이터를 역규범화(반범식)하고 2차 조회 방식으로 데이터를 얻는 것이 가장 현명한 선택이다.역규범화는 가장 강력하고 유연하다고 할 수 있다.
물론 이것은 관리 원가를 가져올 것이다.우리는 데이터 간의 관계를 수동으로 관리하고 필요한 조회나 필터 조건을 이용하여 다양한 유형을 연결해야 한다.
결론과 회고
이 문서의 내용은 상대적으로 지루하다. 다음은 간단한 회고이다.
Inner Object
Nested
Parent/Child
역규범화
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
kafka connect e elasticsearch를 관찰할 수 있습니다.No menu lateral do dashboard tem a opção de connectors onde ele mostra todos os clusters do kafka connect conectados atu...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.