Pochodzę z relacyjnej bazy danych i próbuję pracować z DynamoDB Amazona
Mam tabelę z kluczem skrótu „DataID” i zakresem „CreatedAt” oraz kilkoma elementami w nim.
Próbuję uzyskać wszystkie elementy, które zostały utworzone po określonej dacie i posortowane według daty. Co jest dość proste w relacyjnej bazie danych.
W DynamoDB najbliższą rzeczą, jaką mogłem znaleźć, jest zapytanie i użycie klucza zakresu większego niż filtr. Jedynym problemem jest to, że do wykonania zapytania potrzebuję klucza skrótu, który mija się z celem.
Więc co robię źle? Czy mój schemat tabeli jest nieprawidłowy, czy klucz skrótu nie powinien być unikalny? czy jest inny sposób zapytania?
źródło
CreatedAt
punktem większym niż określony.Biorąc pod uwagę aktualną strukturę tabeli, nie jest to obecnie możliwe w DynamoDB. Ogromnym wyzwaniem jest zrozumienie, że klucz Hash tabeli (partycji) należy traktować jako tworzenie oddzielnych tabel. Pod pewnymi względami jest to naprawdę potężne (pomyśl o kluczach partycji jako o tworzeniu nowej tabeli dla każdego użytkownika lub klienta itp.).
Zapytania można wykonywać tylko w jednej partycji. To naprawdę koniec historii. Oznacza to, że jeśli chcesz zapytać według daty (będziesz chciał użyć ms od epoki), wówczas wszystkie elementy, które chcesz pobrać w pojedynczym zapytaniu, muszą mieć ten sam skrót (klucz partycji).
Powinienem to zakwalifikować. Absolutnie możesz
scan
według kryterium, którego szukasz, to nie jest problem, ale oznacza to, że będziesz patrzeć na każdy wiersz w swojej tabeli, a następnie sprawdzać, czy ten wiersz ma datę pasującą do twoich parametrów. Jest to naprawdę drogie, zwłaszcza jeśli zajmujesz się przechowywaniem wydarzeń według daty (tj. Masz dużo wierszy).Możesz ulec pokusie umieszczenia wszystkich danych na jednej partycji, aby rozwiązać problem, i absolutnie możesz, jednak Twoja przepustowość będzie boleśnie niska, biorąc pod uwagę, że każda partycja otrzymuje tylko ułamek całkowitej ustawionej kwoty.
Najlepszą rzeczą do zrobienia jest określenie bardziej przydatnych partycji do utworzenia w celu zapisania danych:
Czy naprawdę musisz patrzeć na wszystkie wiersze, czy jest to tylko wiersze określonego użytkownika?
Czy byłoby dobrze najpierw zawęzić listę według miesiąca i wykonać wiele zapytań (jedno na każdy miesiąc)? Lub według roku?
Jeśli wykonujesz analizę szeregów czasowych, istnieje kilka opcji, zmień klucz partycji na coś obliczonego,
PUT
abyquery
ułatwić sobie pracę, lub użyj innego produktu aws, takiego jak kinezy, który nadaje się do rejestrowania tylko przez dołączanie.źródło
yyyy
i hash na tym, ale także utwórzcreated
datę, której możesz użyć jako klucza zakresu. Następnie otrzymujesz 10 GB danych rocznie (27 MB dziennie), co prawdopodobnie jest w porządku w innych okolicznościach. Oznacza to, że musisz tworzyć kwerendę rocznie, gdy zapytania dotyczące dat przekraczają granicę roku, ale przynajmniej zadziała i jest bezpieczniejsze niż tworzenie fikcyjnego klucza mieszającego.Podejście, które zastosowałem, aby rozwiązać ten problem, polega na utworzeniu globalnego indeksu wtórnego, jak poniżej. Nie jestem pewien, czy to najlepsze podejście, ale miejmy nadzieję, że komuś przyda się.
Ograniczenie nałożone na użytkownika interfejsu API HTTP do określenia liczby dni pobierania danych, domyślnie 24 godziny.
W ten sposób zawsze mogę określić HashKey jako dzień bieżącej daty, a RangeKey może używać operatorów> i <podczas pobierania. W ten sposób dane są również rozproszone na wielu fragmentach.
źródło
Twój klucz Hash (główny rodzaj) musi być unikalny (chyba że masz zakres taki jak podany przez innych).
W twoim przypadku, aby wykonać zapytanie o twoją tabelę, powinieneś mieć dodatkowy indeks.
Twój klucz skrótu to ID Twój dodatkowy indeks jest zdefiniowany jako: DataID-Utworzony-indeks (to nazwa, której będzie używać DynamoDB)
Następnie możesz wykonać takie zapytanie:
Zasadniczo Twoje zapytanie wygląda następująco:
Indeks pomocniczy zwiększy wymagane jednostki pojemności odczytu / zapisu, więc musisz to wziąć pod uwagę. Nadal jest o wiele lepsze niż skanowanie, które będzie kosztowne w odczytach i czasie (i jest ograniczone do 100 pozycji, jak sądzę).
Może to nie jest najlepszy sposób na zrobienie tego, ale dla kogoś przyzwyczajonego do RD (jestem przyzwyczajony do SQL) jest to najszybszy sposób na uzyskanie produktywności. Ponieważ nie ma ograniczeń co do schematu, możesz uruchomić coś, co działa, a gdy masz przepustowość do pracy w najbardziej efektywny sposób, możesz wszystko zmienić.
źródło
Możesz ustawić klucz Hash w podobny sposób jak identyfikator „kategorii produktu”, a następnie klucz zakresu jako kombinację znacznika czasu z unikalnym identyfikatorem dołączonym na końcu. W ten sposób znasz klucz skrótu i nadal możesz zapytać o datę z większym niż.
źródło
Możesz mieć wiele identycznych kluczy mieszających; ale tylko wtedy, gdy masz zmienny klucz zakresu. Pomyśl o tym jak o formatach plików; możesz mieć 2 pliki o tej samej nazwie w tym samym folderze, o ile ich format jest inny. Jeśli ich format jest taki sam, ich nazwa musi być inna. Ta sama koncepcja dotyczy kluczy mieszających / zakresowych DynamoDB; pomyśl tylko o haszu jako nazwie i zakresie jako formacie.
Nie pamiętam też, czy mieli je w czasie PO (nie sądzę, że mieli), ale teraz oferują lokalne indeksy wtórne.
Rozumiem, że powinno to teraz umożliwiać wykonywanie żądanych zapytań bez konieczności wykonywania pełnego skanowania. Wadą jest to, że te indeksy muszą być określone podczas tworzenia tabeli, a także (moim zdaniem) nie mogą być puste podczas tworzenia elementu. Ponadto wymagają dodatkowej przepustowości (choć zwykle nie tak dużej jak skanowanie) i pamięci, więc nie jest to idealne rozwiązanie, ale dla niektórych realna alternatywa.
Nadal jednak polecam odpowiedź Mike'a Branta jako preferowaną metodę korzystania z DynamoDB; i sam używam tej metody. W moim przypadku mam po prostu tabelę centralną z tylko kluczem mieszającym jako moim identyfikatorem, następnie tabele pomocnicze, które mają skrót i zakres, które można odpytać, a następnie element kieruje kod bezpośrednio do „interesującego elementu” w tabeli centralnej .
Dodatkowe dane dotyczące indeksów wtórnych można znaleźć w dokumentacji Amazon DynamoDB tutaj dla zainteresowanych.
W każdym razie miejmy nadzieję, że pomoże to każdemu, kto wydarzy się w tym wątku.
źródło
Zaktualizowana odpowiedź Nie ma wygodnego sposobu na zrobienie tego za pomocą Dynamo DB Queries z przewidywalną przepustowością. Jedną (nieoptymalną) opcją jest użycie GSI ze sztucznym HashKey & CreatedAt. Następnie zapytaj za pomocą samego HashKey i podaj ScanIndexForward, aby uporządkować wyniki. Jeśli możesz wymyślić naturalny HashKey (powiedz kategorię przedmiotu itp.), Ta metoda jest zwycięzcą. Z drugiej strony, jeśli zachowasz ten sam HashKey dla wszystkich elementów, wpłynie to na przepustowość głównie wtedy, gdy zestaw danych przekroczy 10 GB (jedna partycja)
Oryginalna odpowiedź: Możesz to zrobić teraz w DynamoDB za pomocą GSI. Ustaw pole „CreatedAt” jako GSI i wprowadź zapytania, takie jak (GT some_date). Przechowuj datę jako liczbę (ms od epoki) dla tego rodzaju zapytań.
Szczegóły są dostępne tutaj: Globalne indeksy wtórne - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Using
To bardzo potężna funkcja. Należy pamiętać, że zapytanie jest ograniczone do (EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN) Warunek - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
źródło
CreatedAt
powinien to być klucz zakresu GSI, musisz wybrać klucz mieszający - i wrócisz do miejsca, w którym zacząłeś, ponieważ będziesz mógł odpytać GTCreatedAt
tylko o określoną wartość klucz skrótu.