select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;
jak powyższe zapytanie będzie działać wewnętrznie w Cassandrze?
zasadniczo wszystkie dane dla partycjiscopeid=35
Iformid=78005
zostaną zwrócone, a następnie filtrowane przez indeksrecord_link_id
. Będzie szukał wpisurecord_link_id
dla9897
i spróbuje dopasować wpisy pasujące do wierszy zwróconych gdziescopeid=35
Iformid=78005
. Zostanie zwrócone przecięcie wierszy dla klawiszy partycji i klawiszy indeksu.
jak wysoki indeks kolumny (record_link_id)wpłynie na wydajność zapytania dla powyższego zapytania?
wysokie indeksy kardynalne tworzą zasadniczo wiersz dla (prawie) każdego wpisu w głównej tabeli. Wpływa to na wydajność, ponieważ Cassandra została zaprojektowana do wykonywania sekwencyjnych odczytów wyników zapytań. Zapytanie indeksowe zasadniczo zmusza Cassandrę do wykonywania losowych odczytów. Wraz ze wzrostem wartości indeksowanej wzrasta również czas potrzebny na znalezienie wartości zapytanej.
czy cassandra dotknie wszystkich węzłów dla powyższego zapytania? Dlaczego?
nie. Powinien dotykać tylko węzła odpowiedzialnego za partycję scopeid=35
I formid=78005
. Indeksy również są przechowywane lokalnie, zawierają tylko wpisy, które są ważne dla lokalnego węzła.
tworzenie indeksu nad kolumnami o wysokiej cardinalności będzie najszybszym i najlepszym modelem danych
problem polega na tym, że podejście nie skaluje się i będzie powolne, jeśliupdate_audit
jest dużym zbiorem danych. MVP Richard Low ma świetny artykuł na temat drugorzędnych indeksów (Sweet Spot dla Cassandra Secondary Indexing), a szczególnie na ten temat:
Jeśli twoja tabela była znacznie większa niż pamięć, zapytanie byłoby bardzo powolne, nawet jeśli zwróciłoby tylko kilka tysięcy wyników. Zwrócenie potencjalnie milionów użytkowników byłoby katastrofalne, nawet jeśli wydaje się, że jest to wydajne zapytanie.
w praktyce oznacza to, że indeksowanie jest najbardziej przydatne do zwracania dziesiątek, może setek wyników. Pamiętaj o tym, gdy następnym razem rozważasz użycie indeksu wtórnego.
teraz Twoje podejście do pierwszego ograniczenia przez określoną partycję pomoże (ponieważ partycja z pewnością powinna zmieścić się w pamięci). Ale wydaje mi się, że lepszym wyborem byłoby, aby record_link_id
był klucz klastrowy, zamiast polegać na indeksie wtórnym.
Edytuj
jak skaluje się Indeks na niskim indeksie cardinality, gdy są miliony użytkowników, nawet jeśli podamy klucz podstawowy
To zależy od szerokości wierszy. Trudną rzeczą w ekstremalnie niskich wskaźnikach cardinality jest to, że % zwracanych wierszy jest zwykle większe. Na przykład rozważ tabelę users
. Ograniczasz za pomocą klucza partycji w zapytaniu, ale nadal zwracanych jest 10 000 wierszy. Jeśli twój indeks znajduje się na czymś takim jak gender
, Twoje zapytanie będzie musiało odfiltrować około połowy tych wierszy, co nie będzie dobrze działać.
indeksy drugorzędne najlepiej sprawdzają się na (z braku lepszego opisu) „środku drogi”. Korzystając z powyższego przykładu tabeli o szerokim wierszu users
, indeks na country
lub state
powinien działać znacznie lepiej niż indeks na gender
(zakładając, że większość z tych użytkowników nie mieszka w tego samego kraju lub stanu).
Edit 20180913
aby uzyskać odpowiedź na pierwsze pytanie „jak powyższe zapytanie będzie działać wewnętrznie w Cassandrze?”, Czy wiesz, jakie jest zachowanie, gdy zapytanie z paginacją?
rozważ następujący schemat, zaczerpnięty z Dokumentacji Sterownika Java (v3.6):
zasadniczo, stronicowanie spowoduje, że zapytanie samo się rozpadnie i powróci do klastra w celu następnej iteracji wyników. Mniej prawdopodobne jest przekroczenie limitu czasu, ale wydajność będzie się zmniejszać, proporcjonalnie do wielkości całkowitego zestawu wyników i liczby węzłów w klastrze.
TL; DR; im więcej żądanych wyników rozdzieli się na więcej węzłów, tym dłużej to potrwa.