Elasticsearch
Różnica między indeksami i typami
Szukaj…
Uwagi
Łatwo jest zobaczyć type takie jak tabela w bazie danych SQL, gdzie index jest baza danych SQL. Nie jest to jednak dobry sposób podejścia do type s.
Wszystkie typy
W rzeczywistości typy są dosłownie tylko polami metadanych dodawanymi do każdego dokumentu przez Elasticsearch: _type . Powyższe przykłady stworzyły dwa typy: my_type i my_other_type . Oznacza to, że każdy dokument powiązany z typami ma automatycznie zdefiniowane dodatkowe pole, takie jak "_type": "my_type" ; jest to indeksowane wraz z dokumentem, co czyni go polem przeszukiwalnym lub filtrowalnym , ale nie wpływa na sam surowy dokument, więc aplikacja nie musi się o to martwić.
Wszystkie typy żyją w tym samym indeksie, a zatem w tych samych zbiorczych fragmentach indeksu. Nawet na poziomie dysku znajdują się w tych samych plikach. Jedyne rozdzielenie, jakie zapewnia utworzenie drugiego typu, jest logiczne. Każdy typ, czy to unikalny, czy nie, musi istnieć w mapowaniach, a wszystkie te mapowania muszą istnieć w stanie klastra. To zużywa pamięć, a jeśli każdy typ jest dynamicznie aktualizowany, zwiększa wydajność wraz ze zmianą mapowań.
W związku z tym najlepszą praktyką jest definiowanie tylko jednego typu, chyba że faktycznie potrzebujesz innych typów. Często spotyka się scenariusze, w których pożądanych jest wiele typów. Na przykład wyobraź sobie, że masz indeks samochodu. Przydaje się podział na wiele typów:
- BMW
- pogoń
- Honda
- mazda
- mercedes
- Nissan
- rangerover
- Toyota
- ...
W ten sposób możesz wyszukać wszystkie samochody lub ograniczyć je według producenta na żądanie. Różnica między tymi dwoma wyszukiwaniami jest tak prosta, jak:
GET /cars/_search
i
GET /cars/bmw/_search
Dla nowych użytkowników Elasticsearch nie jest oczywiste, że druga forma jest specjalizacją pierwszej formy. Dosłownie zostaje przepisany na:
GET /cars/_search
{
"query": {
"bool": {
"filter": [
{
"term" : {
"_type": "bmw"
}
}
]
}
}
}
Po prostu odfiltrowuje każdy dokument, który nie został zindeksowany za pomocą pola _type którego wartość to bmw . Ponieważ każdy dokument jest indeksowany ze swoim typem jako pole _type , służy to jako dość prosty filtr. Jeśli w którymkolwiek z przykładów podano rzeczywiste wyszukiwanie, filtr zostałby odpowiednio dodany do pełnego wyszukiwania.
W związku z tym, jeśli typy są identyczne, o wiele lepiej jest podać jeden typ (np. manufacturer w tym przykładzie) i skutecznie go zignorować. Następnie w każdym dokumencie wyraźnie podaj pole o nazwie make lub dowolna nazwa i ręcznie filtruj je, gdy tylko chcesz. Zmniejszy to rozmiar twoich mapowań do 1/n gdzie n jest liczbą oddzielnych typów. Dodaje kolejne pole do każdego dokumentu na korzyść skądinąd uproszczonego mapowania.
W Elasticsearch 1.xi 2.x takie pole należy zdefiniować jako
PUT /cars
{
"manufacturer": { <1>
"properties": {
"make": { <2>
"type": "string",
"index": "not_analyzed"
}
}
}
}
- Nazwa jest dowolna.
- Nazwa jest dowolna i może być zgodna z nazwą typu, jeśli jej również chcesz.
W Elasticsearch 5.x powyższe będzie nadal działać (jest przestarzałe), ale lepszym sposobem jest użycie:
PUT /cars
{
"manufacturer": { <1>
"properties": {
"make": { <2>
"type": "keyword"
}
}
}
}
- Nazwa jest dowolna.
- Nazwa jest dowolna i może być zgodna z nazwą typu, jeśli jej również chcesz.
Typy powinny być stosowane oszczędnie w obrębie indeksów, ponieważ nadymają odwzorowania indeksów, zwykle bez większych korzyści. Musisz mieć co najmniej jeden, ale nic nie mówi, że musisz mieć więcej niż jeden.
Często zadawane pytania
- Co jeśli mam dwa (lub więcej) typy, które są w większości identyczne, ale które mają kilka unikalnych pól dla każdego typu?
Na poziomie indeksu nie ma różnicy między jednym typem używanym z kilkoma rzadko używanymi polami a między wieloma typami, które współużytkują kilka nierzadkich pól z kilkoma nieudostępnionymi (co oznacza, że drugi typ nigdy nie używa pola (s)).
Inaczej mówiąc: rzadko używane pole jest rzadkie w całym indeksie, niezależnie od typów . Rzadkość nie korzysta - ani nie szkodzi - indeksowi tylko dlatego, że jest zdefiniowany w osobnym typie.
Powinieneś po prostu połączyć te typy i dodać osobne pole typu.
- Dlaczego osobne typy muszą definiować pola dokładnie w ten sam sposób?
Ponieważ każde pole jest tak naprawdę zdefiniowane tylko raz na poziomie Lucene, bez względu na liczbę typów. Fakt, że typy w ogóle istnieją, jest cechą Elasticsearch i jest tylko logiczną separacją.
- Czy mogę zdefiniować osobne typy z tym samym polem zdefiniowanym inaczej?
Nie. Jeśli uda ci się znaleźć sposób na wykonanie tego w ES 2.x lub nowszej, powinieneś otworzyć raport o błędzie . Jak zauważono w poprzednim pytaniu, Lucene traktuje je wszystkie jako jedno pole, więc nie ma sposobu, aby działało to odpowiednio.
ES 1.x pozostawił to jako domniemane wymaganie, które pozwoliło użytkownikom stworzyć warunki, w których odwzorowania jednego fragmentu w indeksie faktycznie różniły się od innego fragmentu w tym samym indeksie. To był w rzeczywistości wyścig i może prowadzić do nieoczekiwanych problemów.
Wyjątki od reguły
- Dokumenty nadrzędne / podrzędne wymagają stosowania oddzielnych typów w ramach tego samego indeksu.
- Rodzic mieszka w jednym typie.
- Dziecko żyje w osobnym typie (ale każde dziecko żyje w tym samym odłamku, co jego rodzic).
- Niezwykle niszowe przypadki użycia, w których tworzenie ton indeksów jest niepożądane, a wpływ rzadkich pól jest lepszy niż alternatywa.
- Na przykład wtyczka monitorująca Elasticsearch, Marvel (1.x i 2.x) lub X-Pack Monitoring (5.x +), sam monitoruje Elasticsearch pod kątem zmian w klastrze, węzłach, indeksach, określonych indeksach (poziom indeksu), a nawet odłamki. Może tworzyć ponad 5 indeksów każdego dnia, aby wyodrębnić te dokumenty, które mają unikalne mapowania, lub może być sprzeczny z najlepszymi praktykami w celu zmniejszenia obciążenia klastra poprzez udostępnienie indeksu (uwaga: liczba zdefiniowanych mapowań jest faktycznie taka sama, ale liczba utworzonych indeksów jest zmniejszona z
ndo 1). - To jest zaawansowany scenariusz, ale musisz wziąć pod uwagę wspólne definicje pól dla różnych typów!
- Na przykład wtyczka monitorująca Elasticsearch, Marvel (1.x i 2.x) lub X-Pack Monitoring (5.x +), sam monitoruje Elasticsearch pod kątem zmian w klastrze, węzłach, indeksach, określonych indeksach (poziom indeksu), a nawet odłamki. Może tworzyć ponad 5 indeksów każdego dnia, aby wyodrębnić te dokumenty, które mają unikalne mapowania, lub może być sprzeczny z najlepszymi praktykami w celu zmniejszenia obciążenia klastra poprzez udostępnienie indeksu (uwaga: liczba zdefiniowanych mapowań jest faktycznie taka sama, ale liczba utworzonych indeksów jest zmniejszona z
Jawne tworzenie indeksu z typem
Przykład wykorzystuje podstawowy HTTP, który łatwo przekłada się na cURL i inne aplikacje HTTP. Pasują również do składni Sense , której nazwa zostanie zmieniona na Console w Kibana 5.0.
Uwaga: Przykład wstawia <#> aby pomóc zwrócić uwagę na części. Należy je usunąć, jeśli go skopiujesz!
PUT /my_index <1>
{
"mappings": {
"my_type": { <2>
"properties": {
"field1": {
"type": "long"
},
"field2": {
"type": "integer"
},
"object1": {
"type": "object",
"properties": {
"field1" : {
"type": "float"
}
}
}
}
}
},
"my_other_type": {
"properties": {
"field1": {
"type": "long" <3>
},
"field3": { <4>
"type": "double"
}
}
}
}
- To jest tworzenie
indexprzy użyciu punktu końcowego tworzenia indeksu. - To tworzy ten
type. - Wspólne pola
types w ramach tego samegoindexmuszą mieć tę samą definicję! ES 1.x nie narzucał ściśle tego zachowania, ale był to wymóg dorozumiany. ES 2.x i wyżej ściśle egzekwują to zachowanie. - Unikalne pola w różnych
typesą w porządku.
Indeksy (lub indeksy) zawierają typy. Typy są wygodnym mechanizmem rozdzielania dokumentów, ale wymagają zdefiniowania - dynamicznie / automatycznie lub jawnie - mapowania dla każdego używanego typu. Jeśli zdefiniujesz 15 typów w indeksie, masz 15 unikalnych mapowań.
Zobacz uwagi, aby uzyskać więcej informacji na temat tej koncepcji i dlaczego możesz chcieć używać typów.
Dynamiczne tworzenie indeksu z typem
Przykład wykorzystuje podstawowy HTTP, który łatwo przekłada się na cURL i inne aplikacje HTTP. Pasują również do składni Sense , której nazwa zostanie zmieniona na Console w Kibana 5.0.
Uwaga: Przykład wstawia <#> aby pomóc zwrócić uwagę na części. Należy je usunąć, jeśli go skopiujesz!
DELETE /my_index <1>
PUT /my_index/my_type/abc123 <2>
{
"field1" : 1234, <3>
"field2" : 456,
"object1" : {
"field1" : 7.8 <4>
}
}
- Jeśli już istnieje (z powodu wcześniejszego przykładu), usuń indeks.
- Indeksuj dokument do indeksu,
my_index, za pomocą typu,my_typei identyfikatoraabc123(może być numeryczny, ale zawsze jest łańcuchem).- Domyślnie dynamiczne tworzenie indeksu jest włączane po prostu przez indeksowanie dokumentu. Jest to świetne rozwiązanie dla środowisk programistycznych, ale niekoniecznie jest dobre dla środowisk produkcyjnych.
- To pole jest liczbą całkowitą, więc po raz pierwszy musi zostać zmapowane. Elasticsearch zawsze zakłada najszerszy typ dla dowolnego typu przychodzącego, więc byłby on odwzorowany jako
longa nieintegerlubshort(oba mogą zawierać1234i456). - To samo dotyczy również tego pola. Zostanie zmapowany jako
doublezamiastfloatjak możesz chcieć.
Ten dynamicznie tworzony indeks i typ z grubsza odpowiadają odwzorowaniu zdefiniowanemu w pierwszym przykładzie. Jednak ważne jest, aby zrozumieć, w jaki sposób <3> i <4> wpływają na automatycznie zdefiniowane odwzorowania.
Możesz to zrobić, dynamicznie dodając kolejny typ do tego samego indeksu:
PUT /my_index/my_other_type/abc123 <1>
{
"field1": 91, <2>
"field3": 4.567
}
- Typ jest jedyną różnicą w stosunku do powyższego dokumentu. Identyfikator jest taki sam i jest w porządku! Nie ma żadnego związku z innym
abc123poza tym, że akurat jest w tym samym indeksie. -
field1już istnieje w indeksie, więc musi to być ten sam typ pola, co zdefiniowany w innych typach. Podanie wartości, która była łańcuchem lub nie była liczbą całkowitą, nie powiodło się (np."field1": "this is some text"lub"field1": 123.0).
Spowodowałoby to dynamiczne tworzenie odwzorowań dla my_other_type w ramach tego samego indeksu, my_index .
Uwaga: Zawsze jest szybsze definiowanie odwzorowań z góry niż dynamiczne wykonywanie go w czasie indeksowania przez Elasticsearch.
Końcowy wynik indeksowania obu dokumentów byłby podobny do pierwszego przykładu, ale typy pól byłyby różne, a zatem nieco marnotrawne:
GET /my_index/_mappings <1>
{
"mappings": {
"my_type": { <2>
"properties": {
"field1": {
"type": "long"
},
"field2": {
"type": "long" <3>
},
"object1": {
"type": "object",
"properties": {
"field1" : {
"type": "double" <4>
}
}
}
}
}
},
"my_other_type": { <5>
"properties": {
"field1": {
"type": "long"
},
"field3": {
"type": "double"
}
}
}
}
- Używa punktu końcowego
_mappingsaby uzyskać mapowania z utworzonego przez nas indeksu. - Dynamicznie utworzyliśmy
my_typew pierwszym kroku tego przykładu. -
field2jest terazlongzamiast liczbyintegerponieważ nie zdefiniowaliśmy go z góry. Może to okazać się marnotrawstwem w przypadku przechowywania na dysku. -
object1.field1jest terazdoublez tego samego powodu co # 3 z tymi samymi konsekwencjami jak # 3.- Technicznie
longmożna skompresować w wielu przypadkach. Jednakdoublenie można skompresować, ponieważ jest liczbą zmiennoprzecinkową.
- Technicznie
- Dynamicznie utworzyliśmy także
my_other_typew drugim kroku tego przykładu. Zdarza się, że mapowanie jest takie samo, ponieważ używaliśmy jużlongidouble.- Pamiętaj, że
field1musi pasować do definicji zmy_type(i tak jest). -
field3jest unikalny dla tego typu, więc nie ma takich ograniczeń.
- Pamiętaj, że