Pracuję nad aplikacją, która wymaga bardzo wysokiej wydajności aktualizacji / wyboru zapytań w bazie danych.
Mam tabelę podstawową (A), która będzie zawierała około 500 rekordów dla jednostki na jeden dzień. I dla każdego użytkownika w systemie tworzona jest odmiana tego bytu na podstawie niektórych preferencji użytkownika i są one przechowywane w innej tabeli (B). Odbywa się to przez zadanie crona, które działa codziennie o północy.
Jeśli więc w tabeli A znajduje się 10 000 użytkowników i 500 rekordów, w tabeli B będzie 5 milionów rekordów tego dnia. W tych tabelach zawsze przechowuję dane na jeden dzień, a o północy archiwizuję dane historyczne w HBase. Ta konfiguracja działa dobrze i do tej pory nie mam problemów z wydajnością.
Ostatnio nastąpiła zmiana wymagań biznesowych, a teraz niektóre atrybuty w tabeli podstawowej A (dla 15-20 rekordów) będą się zmieniać co 20 sekund i na tej podstawie muszę ponownie obliczyć niektóre wartości dla wszystkich tych rekordów zmian w tabeli B dla wszyscy użytkownicy. Mimo że zmienia się tylko 20 rekordów głównych, muszę dokonać ponownego obliczenia i zaktualizować 200 000 rekordów użytkowników, co zajmuje więcej niż 20 sekund, a następnie następna aktualizacja nastąpi ostatecznie, w wyniku czego wszystkie zapytania Select zostaną umieszczone w kolejce. Dostaję około 3 żądań / 5 sekund od użytkowników online, co powoduje 6-9 Wybierz zapytania. Aby odpowiedzieć na żądanie interfejsu API, zawsze używam pól w tabeli B.
Mogę kupić większą moc obliczeniową i rozwiązać tę sytuację, ale jestem zainteresowany posiadaniem odpowiednio skalowanego systemu, który może obsłużyć nawet milion użytkowników.
Czy ktoś może tu zaproponować lepszą alternatywę? Czy relacyjna baza danych nosql + mi tu pomaga? Czy są jakieś platformy / magazyny danych, które pozwolą mi często aktualizować dane bez blokowania, a jednocześnie dadzą mi elastyczność uruchamiania wybranych zapytań na różnych polach w jednostce?
źródło
Odpowiedzi:
Wygląda na to, że tabela
B
jest rodzajem pamięci podręcznej. Ale tego rodzaju pamięć podręczna, która obniża wydajność ...Nawet jeśli masz 25 zapytań na sekundę, możesz odmówić użycia tabeli
B
i obliczyć odpowiedź dla każdego żądania.W każdym razie , jeśli masz 30 sekund opóźnienia na aktualizację 20 rekordów - jest to błąd w architekturze oprogramowania (mylę się, jeśli twoja DB oblicza pierwsze 10 ^ 100 znaków PI dla każdego rekordu).
Jak wiem, relacyjna baza danych bez brzydkich zapytań SQL, z indeksami i mniej niż 1 000 000 rekordów będzie działać idealnie dla prawie wszystkich zapytań.
Spróbuj odmówić użycia tabeli
B
i dodaj do niej odpowiednie indeksyA
(większość nowoczesnych baz danych ma narzędzie pomocnicze). Następnie: spróbuj zoptymalizować strukturę danych (tabelęA
) i zapytanie (używając analizatora zapytań lub z ekspertami SQL), aby przyspieszyć obliczenia. Jeśli zaktualizujesz tylko 20 rekordów - istnienie indeksów nie zaszkodzi wydajności procesu aktualizacji , ale znacznie poprawi szybkość wyboru .źródło
Pytanie naprawdę brzmi, jaki system oblicza rekord do wstawienia do B i jaki jest rozmiar danych B.
Każda baza danych (np. MSSQL) powinna być w stanie obsłużyć liczbę wstawek, o których mówisz, bez problemu, zakładając, że obiekt nie jest ogromny.
Aktualizacje mogą być trudniejszym problemem, ale przy odpowiednim indeksowaniu i blokowaniu znowu nie powinno być dużym problemem.
99% czasu, kiedy widzę taki problem, wynika z obliczenia rekordu B przez zapisany proc. Spowoduje to obciążenie całego serwera db
W takim przypadku rozwiązaniem jest przeniesienie tego kodu do usługi offline, którą można wywołać za pośrednictwem systemu kolejkowania.
Tak więc komunikat o aktualizacji A uruchomiłby proces roboczy, który przechodziłby przez użytkowników i tworzyłby komunikat o aktualizacji B dla każdego użytkownika
Drugi proces roboczy B pobierałby aktualizację Użytkownik X z danymi Zdarzenie A tworzył rekord B i aktualizował DB
Można to skalować, dodając więcej pól z robotami kolejkowymi, dzięki czemu masz więcej mocy obliczeniowej za obliczeniami, pozostawiając db swobodnie koncentrować się na aktualizacjach i selekcjach.
możesz dalej optymalizować, oddzielając selekcje od aktualizacji / wstawek. mają nową bazę danych, która pobiera wszystkie wybrane żądania, jako podrzędną replikację, stara baza danych, która pobiera wszystkie aktualizacje.
źródło
Jeśli pracujesz w Amazon, rozważę DynamoDB. Opiera się na pamięci flash. Oto link do niego: https://aws.amazon.com/dynamodb/ .
Jakiego rodzaju RDBMS używasz? Możesz zwiększyć wydajność, używając UDF lub pola obliczeniowego w widoku. Czy przeprowadzasz obliczenia w bazie danych za pomocą pojedynczego zapytania aktualizacyjnego, czy wybierasz dane z bazy danych, uruchamiasz obliczenia w innym procesie, a następnie ładujesz je z powrotem?
Oracle jest domyślnie skonfigurowany do korzystania z trybu migawki, co oznacza, że wiersze nie są blokowane podczas aktualizacji, a jednoczesne wybory uzyskują oryginalną wartość. SQL Server jest domyślnie skonfigurowany z pesymistyczną współbieżnością, więc jednoczesne wybory będą blokować do czasu zakończenia aktualizacji. Niektóre wersje programu SQL Server można przełączyć w tryb migawki, jednak znacznie zwiększa to obciążenie tabeli tymczasowej.
W jakim środowisku pracujesz? Jeśli jest to RDBMS w instancji EC2 w Amazon, spróbuj umieścić pliki danych DB na lokalnym dysku flash. Widziałem różnicę wielkości rzędu podczas przenoszenia plików z EBS na dysk lokalny.
źródło