Dlaczego Cassandra odradza tworzenie indeksu na kolumnach o wysokiej liczności?

10

Dokumentacja Cassandra stwierdza,

Nie używaj indeksu w następujących sytuacjach:

  • W kolumnach o wysokiej liczności, ponieważ następnie przeszukujesz ogromną liczbę rekordów w celu uzyskania niewielkiej liczby wyników. Zobacz problemy przy użyciu indeksu kolumny o wysokiej liczności poniżej.

To idzie,

Jeśli utworzysz indeks w kolumnie o wysokiej liczności, która ma wiele różnych wartości, zapytanie między polami spowoduje wiele prób uzyskania bardzo niewielu wyników. W tabeli z miliardem piosenek wyszukiwanie piosenek według pisarza (wartość, która jest zwykle unikalna dla każdej piosenki) zamiast według ich wykonawcy, może być bardzo nieefektywne. Prawdopodobnie bardziej efektywne byłoby ręczne utrzymywanie tabeli jako formy indeksu zamiast korzystania z wbudowanego indeksu Cassandra. W przypadku kolumn zawierających unikalne dane czasami wygodniej jest używać indeksu dla wygody, o ile wolumin zapytania do tabeli mającej indeksowaną kolumnę jest umiarkowany i nie jest pod stałym obciążeniem.

Ale tak naprawdę nigdy nie odpowiada na pytanie: dlaczego jest nieefektywne? Nie mam pojęcia, co oznacza „ręczne utrzymywanie tabeli jako formy indeksu”. Ale w pewnym sensie jest to sprzeczne z „… czasem wygodnym jest użycie indeksu dla wygody, o ile objętość zapytania jest umiarkowana…”

Czy to po prostu próbuje mi powiedzieć, żebym używał PK, kiedy i gdzie mogę? Jaka jest nieefektywność? Rozumiem, że zapytanie, które trafiłoby do indeksu, musiałoby wykonać zapytanie do każdego węzła w klastrze, a następnie każdy węzeł przeprowadziłby wyszukiwanie w swoim lokalnym indeksie, a wyniki zostałyby następnie zagregowane. To niekoniecznie jest drogie (każde wyszukiwanie indeksu powinno być dość tanie), z wyjątkiem tego, że płacimy za opóźnienie w sieci, ponieważ musimy czekać na najwolniejszy węzeł partii. Czy coś tu brakuje?

Ale jeśli mam kolekcję zawierającą bajillion przedmiotów, które - w rzadkich przypadkach - muszą zostać wyszukane za pomocą innego, ale prawie unikalnego atrybutu… jest to właściwe zastosowanie, prawda?

¹Każdy? IDK, jeśli replikacja oznacza, że ​​może to trafić 1/3 klastra dla współczynnika replikacji 3, czy nie?

Tanatos
źródło

Odpowiedzi:

6

Z indeksem Cassandra ( tj. „Indeksem wtórnym”, w przeciwieństwie do kluczy podstawowych), każdy węzeł musi wysłać zapytanie do swoich danych lokalnych, aby odpowiedzieć na zapytanie (patrz FAQ indeksów wtórnych Cassandra ). Indeksy te są również budowane przy użyciu procesu w tle . To tło oznacza, że ​​indeks może zwracać fałszywe negatywy pod względem trafień (lub fałszywe pozytywy pod względem braków).

Oznacza to, że w kolumnie o wysokiej liczności szybkość zmian ( tj. Dodawania / usuwania) z tej kolumny może być dość wysoka. I tak, jeśli ta szybkość zmian jest szybsza niż aktualizacja indeksu za pomocą procesu w tle, wówczas użycie indeksu jest „nieefektywne” (indeks wykonuje więcej pracy niż jest to potrzebne aplikacji, co często może dać złą odpowiedź) .

Bardziej efektywne podejście, jeśli chodzi o zapytania dokładność może być utrzymanie drugi stół , raczej niż indeks wtórnego. Tabele, w przeciwieństwie do indeksów , są traktowane jak każda inna tabela. Są one bardziej prawdopodobne, aby dać swojej aplikacji wyniki kwerendy nie spodziewa . Minusem jest to, że utrzymywanie tabeli jako indeksu , w porównaniu z „wtórnym indeksem” Cassandry, są teraz ograniczeniami aplikacji ( tj. Kod aplikacji musi teraz wiedzieć, jak wstawiać / usuwać wiersze z tej tabeli „indeksu”, i aby zsynchronizować dwie tabele poprzez „uzgadnianie” na poziomie aplikacji).

Mam nadzieję że to pomoże!

Castaglia
źródło
To, że indeksy są budowane przy użyciu procesu w tle, jest… brzydkie. Zakładam, że fałszywe alarmy są widoczne dla użytkownika? (Nie rozumiem, jak by nie były). Jedyne pytanie, na które wciąż mam pytanie, brzmi: „Oznacza to, że w kolumnie o wysokiej liczności szybkość zmian (tj. Dodawania / usuwania) z tej kolumny może być dość wysoko. ” - Rozumiem, dlaczego tempo zmian w stosunku do budowania indeksu bg byłoby złe, ale wciąż nie rozumiem, co ma z tym wspólnego wysoka kardynalność. (Z pewnością nawet kolumna niskiej kardynalności spotkałaby się z tym samym losem, nie?)
Thanatos
Tak, kolumna niskiej kardynalności spotkałaby ten sam los. Przyznaję, że moje myślenie było trochę niewyraźne. Ja przy założeniu , że wysoki wskaźnik liczność byłoby raczej mieć wyższy wskaźnik zmiany (a zatem bardziej prawdopodobnie wykazują fałszywie pozytywne / negatywne); najbardziej istotna jest szybkość zmian (w stosunku do procesu indeksowania w tle), a nie liczność.
Castaglia,
2

Trochę terminologii: Tabela nadrzędna to tabela, na której tworzony jest indeks. Pomocnicza tabela indeksowa to tabela utworzona w celu utrzymania indeksu w innej tabeli.

Dane wtórnej tabeli indeksu są przechowywane w tym samym węźle, co dane tabeli nadrzędnej. Partycjoner Cassandra nie dzieli i nie dystrybuuje danych tabeli indeksów. Jeśli więc chcesz przeprowadzić wyszukiwanie w kolumnie indeksu, wszystkie węzły są pytane, a nie tylko węzły repliki zawierające dane. (węzeł koordynujący nie wie, gdzie znajdują się dane) https://www.datastax.com/dev/blog/cassandra-native-secondary-index-deep-dive

W przypadku kolumn o dużej liczności, takich jak ssn lub jakiś inny unikalny identyfikator, będzie mapowanie jeden do jednego z kluczem podstawowym. Jeśli utworzysz indeks w takiej kolumnie, dane rezydują na liczbie węzłów współczynnika replikacji, ale wywołanie wyszukiwania jest wykonywane na wszystkich węzłach. W najlepszym przypadku koordynator trafia bezpośrednio w węzły zawierające dane, a po osiągnięciu poziomu spójności otrzymujesz wynik. Co gorsza, jeśli dane, których szukasz, nie są obecne w indeksie, czekasz, aż wszystkie węzły odpowiedzą, że nie ma danych. Tak więc dla każdego wywołania wtórnej tabeli indeksu trafiają wszystkie węzły. Porównaj to z liczbą trafień tylko węzła replikacji dla każdego wywołania odnośnika, na wypadek gdyby tabela była normalną tabelą C *.

Pramod Sivaraju
źródło