Jak przechowywać zamówione przedmioty, które często zmieniają pozycję w DB
Muszę być w stanie przechowywać dużą listę zamówionych przedmiotów w DB. Jak na razie to prosto do przodu:
ID Position OtherFields
1 45 ...
2 4736 ...
3 514 ...
...
W zapytaniach zawsze potrzebuję tylko kilku elementów (filtrowanych na podstawie innych pól), ale w odpowiedniej kolejności. Łatwe również umieszczenie indeksu na pozycji i użycie "order by Position".
Teraz problem : przedmioty często zmieniają swoją pozycję, a nie tylko o 1 lub 2. Jeśli ID 2 zmieni pozycję z 4736 na 2000, muszę zaktualizować jego pozycję i Pozycja wszystkich elementów pomiędzy starą pozycją 2000 a 4735, dodając po 1 w każdym wierszu. I to nie tylko jeden identyfikator zmienia się w każdej transakcji, ale kilka, i może być wiele transakcji w krótkim czasie.
Myślę, że najbardziej eleganckim sposobem radzenia sobie z problemem update byłoby użycie linked list zamiast kolumny Position, gdzie mogę po prostu usunąć ID 2 ze starej pozycji, łącząc poprzednika z następcą, a następnie wstawić go gdzie indziej, łącząc go między nowym poprzednik i następca. Byłaby to stała i niewielka liczba aktualizacji na zmianę pozycji i byłby to również mój preferowany sposób obsługi zmian (w moim przypadku w Javie). Jednak to rodzi problem N+1 dla zapytań w prawidłowej kolejności - nawet dla kilku elementów, muszę przejść przez całą listę w najgorszym przypadku, aby dowiedzieć się ich prawidłowej kolejności.
Więc moje pytanie brzmi: co polecacie, aby uzyskać dobrą równowagę między niezbędnymi aktualizacjami i wydajność zapytań?
Jak na razie widzę dwa obiecujące Kierunki:
Czy istnieje DBMS (najlepiej OpenSource), który może obsługiwać połączone listy nie tylko z cukrem składniowym, ale także z dobrą wydajnością, np. używając wewnętrznych indeksów dla połączonych elementów?
Być może byłoby to również opcja, aby po prostu mieć BLOB, w którym cała powiązana lista byłaby przechowywana! Jak duża może mieć Taka Podlinkowana lista / ile pamięci zużyje w DB i po pobraniu powiedzmy 1.000.000 wpisów? Używam Javy + Hibernate w razie potrzeby. Wyobrażam sobie, że przetwarzanie nawet całej listy w pamięci po pobraniu Bloba powinno być dość szybkie!?
Ale oczywiście inne pomysły są mile widziane!
3 answers
Jeśli złagodzisz ograniczenie, że kolumna Position
musi zawierać liczby całkowite od 1 do N i zamiast tego pozwolić, aby zawierała dowolne liczby, możesz efektywnie wyszukiwać i aktualizować.
Możesz wstawić pozycję między dwoma innymi pozycjami a i B, obliczając średnią (A + B) DIV 2. Na przykład, Jeśli A to 10000, A B to 12000, to twoja nowa pozycja to 11000. Od czasu do czasu zabraknie Ci luk z powodu grupowania, w którym to momencie możesz przejrzeć całą tabelę redystrybucja pozycji bardziej równomiernie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-03 18:12:10
A co z użyciem dziesiętnego dla pozycji? Jeśli to zrobisz, możesz użyć następującej metody, aby umieścić go między innymi pozycjami:
Oryginalne zapisy to:
ID Position Otherfields
--------------------------
1 1.0
2 2.0
.
.
.
5000 5000.0
Następnie przesuń ID 1 do tuż przed 5000
ID Position Otherfields
--------------------------
1 4999.9
2 2.0
.
.
.
5000 5000.0
Teraz powiedzmy, że chcesz umieścić ID 2 między 1 A 5000:
ID Position Otherfields
--------------------------
1 4999.9
2 4999.91
.
.
.
5000 5000.0
W ten sposób zmieniasz tylko jeden rekord...
Aktualizacja:
Po ponownym przeczytaniu sugestii @ Marka Byersa wydaje się, że nasze rozwiązania są bardzo podobne, choć przy użyciu dziesiętne wydaje mi się dużo prostsze...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-03 18:27:51
Poniższe mogą być pomocne. Nie odpowiada bezpośrednio na twoje pytania, ale może rzucić trochę światła na to, jak to zrobić (jeśli jest to możliwe dla Twoich wymagań): {]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:43