Jak dane przerosły nasze przewidywanie przyszłości
Dzisiaj chcę się z Tobą podzielić wydarzeniem, które aktualnie dzieje się u mnie w pracy. Konkretnie w jednym z projektów, które rozwijam.
Trochę ponad 2 lata temu zaczęliśmy dla klienta robić aplikację, która, w dużym skrócie, prezentuje w jednej tabeli dane dotyczące funduszy. I z tej aplikacji korzysta może ze 20 osób. A dane do niej importujemy co kilka minut z innych systemów. I tych danych nie jest dużo bo jest to kwestia około tysiąca funduszy, dla których w kilku tabelach jest od jednego do kilku wierszy. Dodatkowo te dane są importowane tylko w godzinach pracy. Także nic szczególnego.
Jednak w poniedziałek dostałem zgłoszenie, że na produkcji zaczynają pojawiać się błędy.
Więc zajrzałem do logów (pamiętaj! logowanie informacji o systemie to 1 dzień pracy oszczędzający tygodnie szukania!). A w tych logach znalazłem, że problem jest z pobieraniem wyników wyszukiwania. Pozostałe zapytania działają poprawnie. Więc to nie problem z wysypaną aplikacją. Ale w tych logach jest też informacja o tym, że błędem jest timeout na połączeniu z bazą danych.
I w tym miejscu szybko połączyłem fakty. Bo po pierwsze to było jedyne zapytanie, które faktycznie mogło zwrócić nawet wszystkie fundusze, a po drugie przypomniałem sobie, że przy imporcie nie usuwaliśmy starych danych.
Szybko więc znalazłem zapytanie. Bo uważałem, że nawet jak będzie tam kilka milionów rekordów to przecież wybieramy tylko najnowszy zestaw.
Ale pierwszy problem był taki, że zapytanie miało jeden mały błąd – najpierw filtrowaliśmy po treści wpisanej przez użytkownika. Dopiero drugim filtrem było wybranie tylko rekordów z najnowszej aktualizacji. Co już powodowało, że warunek z LIKE
był robiony na całej tabeli.
Drugim problemem faktycznie okazało się nieusuwanie starych danych.
Ale ile tego może się uzbierać przez trochę ponad rok działania? (nie dwa lata bo na produkcję poszliśmy po kilku miesiącach od startu).
Otóż danych w największej tabeli zebrało 75 milionów rekordów. Do tego po kilkadziesiąt milionów wpisów w tabelach pomocniczych.
A jak się dowiedziałem od administratorów baz danych – nasza baza dostała tylko 2GB RAMu. I z tym „ogromem” pamięci musiała robić to LIKE
na kilkudziesięciu milionach wpisów jeszcze złożonych z kilku tabel przez JOIN
.
Całość stanęła na tym, że admini uruchomili skrypt usuwający dane starsze niż miesiąc (trwało to chyba z godzinę lub dłużej), a ja dostałem nowe zdanie jakim jest przejrzenie poprawności zapytań i dodanie mechanizmu czyszczenia danych, których nie musimy już trzymać.
Co prawda nie ja projektowałem aplikację na początku ale wstyd mi, że przez ten czas sam nie zgłosiłem pomysłu i potrzeby dodania dbania o bazę. A dodatkowo nauczka jest taka, że baza danych to nie po prostu worek na dane, do którego możemy pchać wszystko bo wszystko przyjmie.
Z czasem bazy danych mogą gromadzić różnorodne śmieci, pozostałości po usuniętych wtyczkach, z niczym nie powiązane metadane, wcześniejsze wersje wpisów. Od czasu do czasu dobrze jest przeprowadzić porządki i usunąć wszystkie te zbędne rzeczy.