Chcę przechowywać posortowaną listę w bazie danych. Chcę wydajnie wykonać następujące operacje.
- Wstaw (x) - Wstaw rekord x do tabeli
- Usuń (x) - Usuń rekord x z tabeli
- Przed (x, n) - zwraca rekordy „n” poprzedzające rekord x na posortowanej liście.
- Po (x, n) - zwraca rekordy „n” następujące po rekordzie x z posortowanej listy.
- Pierwszy (n) - Zwraca pierwsze rekordy „n” z posortowanej listy.
- Last (n) - Zwraca ostatnie „n” rekordy z posortowanej listy.
- Porównaj (x, y) - Biorąc pod uwagę dwa rekordy xiy z tabeli, sprawdź, czy x> y.
Prostą metodą, o której mógłbym pomyśleć, jest zapisanie w tabeli i zapytaniu jakiegoś atrybutu „ranga” poprzez sortowanie według tego atrybutu. Ale w tej metodzie wstawianie / modyfikowanie rekordu o randze staje się kosztowną operacją. Czy istnieje lepsza metoda?
W szczególności chcę zaimplementować tabelę za pomocą SimpleDB firmy Amazon. Ale ogólna odpowiedź na relacyjną bazę danych również powinna być pomocna.
Aktualizacja profilu obciążenia:
Ponieważ planuję to dla aplikacji internetowej, zależy to od liczby użytkowników korzystających z aplikacji.
Jeśli jest 100 000 aktywnych użytkowników (super optymizm: P), to mój bardzo przybliżony szacunek na dzień
500k wybiera, 100k wstawia i usuwa, 500k aktualizacji
Spodziewałbym się, że stół wzrośnie do 500 tys.
Chcę zoptymalizować operacje aktualizacji, wstawiania i porównywania. Ranga przedmiotów będzie się ciągle zmieniać i muszę aktualizować tabelę.
źródło
Odpowiedzi:
Jeśli ranga nie jest całkowicie arbitralna, ale można ją wyprowadzić z innej własności (np. Imię, wynik gracza itp.), Przyjrzyj się odpowiedzi Joela .
Jeśli jest to dowolna właściwość twoich danych, to powinna być przechowywana jako kolumna w twojej tabeli rekordów. Zakładając, że Amazon SimpleDB jest podobny do typowego RDBMS, możesz następnie zindeksować tę kolumnę i szybko zaspokoić wszystkie powyższe zapytania za pomocą odpowiedniej strategii indeksowania. Jest to normalne w przypadku RDBMS.
Biorąc pod uwagę, że oczekujesz wysokiej aktywności wstawiania i aktualizacji, ale także stosunkowo wysokiej aktywności odczytu, zalecam wykonanie następujących czynności:
INCLUDE
-ing rangę, lub po prostu zapisz, jeśli masz klastrowane rangi) spełniłby zapytanie 7.FILLFACTOR
w SQL Server). Jest to szczególnie ważne, jeśli skupisz się na rankingu.Jeśli spodziewasz się, że 100K + odczytów na stole o wielkości 100K + nie polecam podejścia z listą połączoną. Nie będzie dobrze skalować do tych rozmiarów.
źródło
FILLFACTOR
, zobaczysz, że zasadniczo chodzi o stworzenie dodatkowej przestrzeni na rekordy w indeksie, tak jak opisywane luki rang tworzą przestrzeń dla zmian i wstawiania rang.Ogólnie używam opisanej przez ciebie metody „rangi”. Zamiast kłopotać się aktualizowaniem wierszy, gdy trzeba było zmienić kolejność elementów, często mogłem uciec od usunięcia wszystkich rekordów z listy i ponownego wstawienia nowych elementów w odpowiedniej kolejności. Ta metoda jest wyraźnie zoptymalizowana do wyszukiwania.
Alternatywnym podejściem byłoby modelowanie rekordów jako połączonej listy przy użyciu kolumny tabeli klucza zwrotnego „poprzednik” w tabeli:
Możesz łatwo pobrać listę oraz dodawać i usuwać elementy przy niewielkim obciążeniu, ale uporządkowanie rekordów we właściwej kolejności będzie trudne. Być może istnieje sprytny sposób na zrobienie tego w jednym zapytaniu, prawdopodobnie z dużą ilością aliasowanych połączeń tabel.
Tego drugiego podejścia często używam, gdy modeluję relację typu drzewo (kategorie, foldery, zestawy i podzbiory). Generalnie miałem jakąś funkcję rekurencyjną, aby zrekonstruować pełne drzewo w mojej aplikacji.
źródło
Myślę, że należy przechowywać właściwość lub właściwości używane do obliczenia rangi, a następnie zbudować nad nimi indeks. Zamiast próbować zmusić bazę danych do fizycznego przechowywania danych w uporządkowanej kolejności lub za pomocą ręcznie zarządzanej połączonej listy, dlaczego nie pozwolić silnikowi bazy danych robić to, do czego został przeznaczony?
źródło
Są to ograniczenia nieobsługiwane przez RDBMS, takie jak simpleDB. Wymaganych funkcji nie można zaimplementować po stronie DB w simpleDB, należy je zaimplementować od strony programowania / aplikacji.
W przypadku RDBMS
SQL server
wymagane funkcje są podstawowe dla indeksu klastrowego.Przed (x, n) - zwraca rekordy „n” poprzedzające rekord x na posortowanej liście. > Wybierz najlepsze n wyników, gdzie x mniej niż wartość i uporządkuj według klauzuli.
Po (x, n) - zwraca rekordy „n” następujące po rekordzie x z posortowanej listy. > Wybierz najlepsze n wyników, gdzie x jest większe od wartości i uporządkuj według klauzuli.
Pierwszy (n) - Zwraca pierwsze rekordy „n” z posortowanej listy. > Wybierz najlepsze n wyników.
Last (n) - Zwraca ostatnie „n” rekordy z posortowanej listy. > Wybierz najlepsze n wyników po zamówieniu według opisu.
źródło
Oto, czego użyłem, aby zmienić ranking mojej tabeli Postgres po każdej wstawce:
W moim przypadku użycia wydajność nie jest problemem, ale pewność, że nigdy się nie złamie lub nie zadziała, jest ważna.
źródło