W tym i kilku kolejnych wpisach poruszymy tematy dotyczące indeksów oraz skupimy się na poprawie dostępu do danych za pomocą indeksów wtórnych (secondary indexes).
DynamoDB zapewnia szybki dostęp do elementów w tabeli poprzez określenie wartości klucza podstawowego. Możemy jednak wykorzystać dostępność jednego lub większej liczby kluczy pomocniczych (lub alternatywnych) w celu zwiększenia wydajności dostępu do danych z atrybutami innymi niż klucz podstawowy. W celu rozwiązania tego problemu możemy utworzyć jeden lub więcej indeksów pomocniczych tabeli i wysyłać żądania zapytania lub skanowania w odniesieniu do tych indeksów.
Indeks pomocniczy/wtórny (secondary index) jest strukturą danych, która zapewnia podzbiór atrybutów z tabeli wraz z kluczem alternatywnym aby wspierać operacje Query. Możemy pobierać dane z indeksu za pomocą zapytania w taki sam sposób jak w przypadku zapytania do tabeli. Tabela może posiadać wiele indeksów wtórnych, które dają aplikacjom dostęp do wielu różnych wzorców zapytań (query patterns). Nie wspomniałem o tym w poprzednim zdaniu, ale skanowanie indeksu odbywa się również w taki sam sposób jak skanowanie na tabeli.
Każdy indeks wtórny jest związany dokładnie z jedną tabelą, z której pobieramy dane. Jest to tabelowa bazowa dla indeksu. Podczas tworzenia indeksu definiujemy klucz alternatywny dla indeksu (klucz partycji i klucz sortowania). Określamy również atrybuty, które mają być rzutowane lub kopiowane z tabeli bazowej do indeksu. DynamoDB kopiuje te atrybuty do indeksu wraz z atrybutami klucza głównego z tabeli bazowej. Możemy wówczas zapytać lub przeskanować indeks tak samo jak w przypadku tych operacji wykonanych na tabeli.
Każdy indeks wtórny jest automatycznie używany przez DynamoDB. Kiedy dodajemy, modyfikujemy lub usuwamy elementy z tabeli podstawowej, wszystkie indeksy na tej tabeli są również aktualizowane aby odzwierciedlić te zmiany.
DynamoDB obsługuje dwa rodzaje indeksów wtórnych:
- Global secondary index (globalny indeks wtórny) – indeks z kluczem partycji i kluczem sortowania, które mogą być różne od kluczy tabeli podstawowej. Globalny indeks wtórny jest uważany za "globalny" ponieważ zapytania na indeksie mogą obejmować wszystkie dane w tabeli podstawowej, we wszystkich partycjach. Globalny indeks wtórny przchowywany jest w swojej własnej przestrzeni partycji z dala od tabeli podstawowej i skaluje się niezależnie od tej tabeli;
- Local secondary index (lokalny indeks wtórny) – indeks, który posiada ten sam klucz partycji co tabela podstawowa ale inny klucz sortowania. Lokalny indeks pomocniczy jest "lokalny" w tym sensie, że każda partycja lokalnego indeksu pomocniczego jest przypisana do partycji tabeli bazowej, która ma tę samą wartość klucza partycji.
Zanim przejdziemy dalej powinniśmy skupić się na wymaganiach aplikacji w celu określenia typu indeksu, którego powinniśmy użyć. Poniższa tabela przedstawia główne różnice pomiędzy globalnym indeksem wtórnym a lokalnym indeksem wtórnym:
Charakterystyka | Global secondary index | Local secondary index |
---|---|---|
Schemat klucza (Key Schema) | Klucz partycji indeksu oraz klucz sortowania (jeżeli występuje) mogą być dowolnymi atrybutami tabeli bazowej typu string, number lub binary | Klucz partycji indeksu jest tym samym atrybutem co klucz partycji tabeli bazowej. Klucz sortowania może być dowolnym atrybutem tabeli bazowej typu string, number lub binary |
Ograniczenia rozmiaru na wartość klucza partycji | Nie ma ograniczeń rozmiaru dla globalnych indeksów wtórnych | Dla każdej wartości klucza partycji, całkowity rozmiar wszystkich indeksowanych elementów musi wynosić 10GB lub mniej |
Operacje na (utworzonym) indeksie | Globalne indeksy wtórne mogą być tworzone podczas tworzenia tabeli. Możemy także dodać nowy globalny indeks wtórny dla istniejącej tabeli lub usunąć istniejący globalny indeks wtórny | Lokalne indeksy wtórne tworzone są w momencie tworzenia tabeli. Nie można dodać lokalnego indeksu wtórnego do istniejącej tabeli ani usunąć istniejących lokalnych wtórnych |
Zapytania i partycje | Globalny indeks wtórny pozwala na zapytanie o całą tabelę, we wszystkich partycjach | Lokalny indeks wtórny pozwala na zapytanie o pojedynczą partycję określoną przez wartość klucza partycji w zapytaniu |
Spójność odczytu (read consistency) | Zapytania do globalnych indeksów wtórnych pozwalają jedynie na odczyt w trybie spójności ostatecznej (eventual consistency) | W przypadku zapytań do lokalnego indeksu wtórnego można wybrać ostatecznie spójny lub silnie spójny (strong consistency) odczyt |
Zużycie przepustowości (Provisioned Throughput) | Każdy globalny indeks wtórny posiada własne ustawienia przepustowości dla odczytu i zapisu. Zapytania lub skanowanie na globalnym indeksie wtórym zużywają jednostki pojemności z indeksu a nie tabeli podstawowej. To samo dotyczy aktualizacji indeksu wtórnego spowodowanych zapisami w tabeli. | Zapytania lub skany na lokalnym indeksie pochłaniają jednostki pojemności odczytu z tabeli bazowej. Gdy zapisujemy do tabeli, jej lokalne indeksy wtórne są również aktualizowane - te aktualizacje zużywają jednostki pojemności zapisu z tabeli bazowej |
Projekcja atrybutów | Przy zapytaniach lub skanowaniu globalnego indeksu wtórnego możemy zażądać tylko atrybutów, które są rzutowane na indeks. DynamoDB nie pobiera żadnych atrybutów z tabeli | Jeżeli zapytamy lub zeskanujemy lokalny indeks wtórny możemy zażądać atrybutów, które nie są rzutowane na indeks. DynamoDB automatycznie pobiera te atrybuty z tabeli |
Jeżeli chcemy utworzyć więcej niż jedną tabelę z indeksami wtórnymi musimy to zrobić sekwencyjnie. Prostym przykładem jest utworzenie pierwszej tabeli i czekanie aż stanie się aktywna. W następnym kroku tworzymy następną tabelę i czekamy aż stanie się aktywna, itd. Jeżeli spróbujemy utworzyć więcej niż jedną tabelę z indeksem wtórnym DynamoDB zwróci nam wyjątek LimitExceededException.
Dla każdego indeksu wtórnego musimy określić następujące elementy:
- typ tworzonego indeksu - globalny indeks wtórny lub lokalny indeks wtórny;
- nazwa indeksu - zasady nazewnictwa indeksów są takie same jak tabel. Nazwa musi być unikalna dla tabeli bazowej z którą jest powiązana, ale możemy użyć tej samej nazwy dla indeksów powiązanych z różnymi tabelami podstawowymi;
-
schemat klucza indeksu - każdy atrybut w schemacie musi być atrybutem najwyższego poziomu typu String, Number lub Binary. Inne typy danych w tym dokumenty i zestawy (sets) nie są dozwolone. Inne wymagania dla schematu klucz zależą od typu indeksu:
- dla globalnego indeksu wtórnego kluczem partycji może być dowolny atrybut skalarny tabeli podstawowej. Klucz sortowania jest opcjonalny i również może być dowolnym atrybutem skalarnym tabeli bazowej;
- dla lokalnego indeksu wtórnego klucz partycji musi być taki sam jak klucz partycji tabeli podstawowej a klucz sortowania musi być atrybutem tabeli podstawowej bez klucza.
- dodatkowe atrybuty (jeżeli występują) w celu rzutowania z tabeli bazowej do indeksu. Atrybuty te są dodatkiem do atrybutów klucza tabeli, które są automatycznie rzutowane do każdego indeksu. Możesz rzutować atrybuty dowolnego typu danych, w tym skalary, dokumenty i zestawy.
-
ustawienia przepustowości dla indeksu, jeżeli jest to koniecznie:
- dla globalnego indeksu wtórnego musisz określić ustawienia jednostek przepustowości odczytu i zapisu. Ustawienia przepustowości są niezależne od ustawień tabeli podstawowej;
- dla lokalnego indeksu wtórnego nie musisz określać ustawień jednostek pojemności odczytu i zapisu – wszystkie operacje odczytu i zapisu na lokalnym indeksie wtórnym korzystają z ustawień przepustowości tabeli podstawowej;
Dla zapewnienia maksymalnej elastyczności zapytań można utworzyć do 20 globalnych indeksów wtórnych (domyślny limit) oraz do 5 lokalnych indeksów wtórnych na tabelę.
Limit globalnych indeksów wtórnych wynosi 5 dla następujących regionów: AWS GovCloud (US-East), AWS GovCloud (US-West) oraz Europa (Stockholm) (w momencie przygotowywania wpisu).
W celu uzyskania szczegółowej listy indeksów wtórnych tabeli należy posłużyć się operacją DescribeTable - zwróci ona nazwę, rozmiar przechowywania oraz liczbę elementów dla każdego indeksu wtórnego na tabeli. Wartości te nie są aktualizowane w czasie rzeczywistym ale są odświeżane mniej więcej co 6 godzin.
Dostęp do danych w indeksie wtórnym można uzyskać za pomocą zapytania lub skanowania. Musimy określić nazwę tabeli podstawowej i nazwę indeksu, który chcesz wykorzystać, podać atrybuty, które mają zostać zwrócone w wynikach oraz wszelkie wyrażenia warunkowe lub filtry, które chcesz wykorzystać. DynamoDB może zwrócić wyniki w kolejności rosnącej lub malejącej.
Wraz z usunięciem tabeli dochodzi również do usunięcia wszystkich indeksów powiązanych z tą tabelą.
W kolejnych wpisach skupimy się na szczegółowym omówieniu globalnych oraz lokalnych indeksów pomocniczych/wtórnych.