Wiem, że sqlite nie radzi sobie dobrze z bardzo dużymi plikami bazy danych, nawet gdy są one obsługiwane (kiedyś na stronie sqlite pojawiał się komentarz, że jeśli potrzebujesz plików powyżej 1 GB, możesz rozważyć użycie rdbms dla przedsiębiorstw. już go nie znajdziesz, może być powiązany ze starszą wersją sqlite).
Jednak dla moich celów chciałbym dowiedzieć się, jak źle jest naprawdę, zanim rozważę inne rozwiązania.
Mówię o plikach danych sqlite w zakresie wielu gigabajtów, od 2 GB. Czy ktoś ma z tym jakieś doświadczenie? Wszelkie wskazówki / pomysły?
database
performance
sqlite
Snazzer
źródło
źródło
Odpowiedzi:
Więc zrobiłem kilka testów z sqlite dla bardzo dużych plików i doszedłem do pewnych wniosków (przynajmniej dla mojej konkretnej aplikacji).
Testy obejmują pojedynczy plik sqlite z jedną tabelą lub wieloma tabelami. Każda tabela miała około 8 kolumn, prawie wszystkie liczby całkowite i 4 indeksy.
Pomysł polegał na wstawieniu wystarczającej ilości danych, tak aby pliki sqlite miały rozmiar około 50 GB.
Pojedynczy stół
Próbowałem wstawić wiele wierszy do pliku sqlite za pomocą tylko jednej tabeli. Gdy plik miał około 7 GB (przepraszam, nie mogę sprecyzować liczby wierszy) wstawianie trwało zbyt długo. Oszacowałem, że mój test wstawienia wszystkich moich danych zajmie około 24 godzin, ale nie zakończył się nawet po 48 godzinach.
To prowadzi mnie do wniosku, że pojedyncza, bardzo duża tabela sqlite będzie miała problemy z wstawieniami i prawdopodobnie innymi operacjami.
Myślę, że nie jest to zaskoczeniem, ponieważ tabela się powiększa, wstawianie i aktualizowanie wszystkich indeksów trwa dłużej.
Wiele tabel
Następnie spróbowałem podzielić dane według czasu na kilka tabel, po jednej na dzień. Dane oryginalnej tabeli 1 zostały podzielone na ~ 700 tabel.
Ta konfiguracja nie miała problemów z wstawieniem, nie trwało dłużej w miarę upływu czasu, ponieważ codziennie tworzona była nowa tabela.
Problemy z próżnią
Jak wskazał i_like_caffeine, polecenie VACUUM jest problemem, im większy jest plik sqlite. W miarę wykonywania większej liczby operacji wstawiania / usuwania fragmentacja pliku na dysku będzie się pogarszać, dlatego celem jest okresowe VACUUM w celu optymalizacji pliku i odzyskania przestrzeni plików.
Jednak, jak wskazano w dokumentacji , powstaje pełna kopia bazy danych, aby wykonać próżnię, której wypełnienie zajmuje bardzo dużo czasu. Im mniejsza baza danych, tym szybciej zakończy się ta operacja.
Wnioski
W przypadku mojej konkretnej aplikacji prawdopodobnie podzielę dane na kilka plików db, jeden dziennie, aby uzyskać najlepszą wydajność próżni oraz szybkość wstawiania / usuwania.
To komplikuje zapytania, ale dla mnie warto zaindeksować tyle danych. Dodatkową zaletą jest to, że mogę po prostu usunąć cały plik db, aby upuścić dane o wartości dziennej (częste działanie mojej aplikacji).
Prawdopodobnie musiałbym również monitorować rozmiar tabeli dla pliku, aby zobaczyć, kiedy prędkość stanie się problemem.
Szkoda, że nie wydaje się być metodą przyrostową próżniowe inne niż próżni auto . Nie mogę go użyć, ponieważ moim celem dla próżni jest defragmentacja pliku (przestrzeń plików nie jest wielka sprawa), czego nie robi auto próżnia. W rzeczywistości dokumentacja mówi, że może to pogorszyć fragmentację, dlatego muszę okresowo robić pełną próżnię na pliku.
źródło
Na naszej platformie korzystamy z DBS 50 GB +. bez skarg działa świetnie. Upewnij się, że robisz wszystko dobrze! Czy używasz predefiniowanych instrukcji? * SQLITE 3.7.3
Zastosuj te ustawienia (zaraz po utworzeniu bazy danych)
Mam nadzieję, że to pomoże innym, działa świetnie tutaj
źródło
PRAGMA main.temp_store = MEMORY;
.Stworzyłem bazy danych SQLite o wielkości do 3,5 GB bez zauważalnych problemów z wydajnością. Jeśli dobrze pamiętam, myślę, że SQLite2 mógł mieć pewne dolne limity, ale nie sądzę, że SQLite3 ma takie problemy.
Zgodnie ze stroną limitów SQLite maksymalny rozmiar każdej strony bazy danych wynosi 32 KB. A maksymalna liczba stron w bazie danych to 1024 ^ 3. Tak więc według mojej matematyki maksymalny rozmiar wynosi 32 terabajty. Myślę, że przekroczysz granice systemu plików, zanim uderzysz w SQLite!
źródło
Wiele powodów, dla których wykonanie wstawek zajęło> 48 godzin, wynika z indeksów. Niezwykle szybciej jest:
1 - Usuń wszystkie indeksy 2 - Wykonaj wszystkie wstawki 3 - Utwórz ponownie indeksy
źródło
Oprócz zwykłej rekomendacji:
Nauczyłem się następujących rzeczy z mojego doświadczenia z SQLite3:
Zmień stół później w razie potrzebyNie możesz dodawać ograniczeń za pomocą ALTER TABLE).Pytanie / komentarz mile widziane. ;-)
źródło
Myślę, że główne zarzuty dotyczące skalowania sqlite to:
źródło
Mam bazę danych SQLite 7 GB. Wykonanie określonego zapytania z łączeniem wewnętrznym zajmuje 2,6 s. Aby to przyspieszyć, próbowałem dodać indeksy. W zależności od tego, które indeksy dodałem, czasami zapytanie spadło do 0,1 s, a czasem nawet do 7. Myślę, że problemem w moim przypadku było to, że jeśli kolumna jest bardzo zduplikowana, wówczas dodanie indeksu obniża wydajność :(
źródło
W dokumentacji SQLite znajdowało się stwierdzenie, że praktyczny limit rozmiaru pliku bazy danych wynosi kilkadziesiąt GB: s. Było to głównie spowodowane koniecznością „przydzielania bitmapy brudnych stron” przez SQLite przy każdym rozpoczęciu transakcji. Zatem 256 bajtów pamięci RAM było wymaganych na każdy MB w bazie danych. Wstawienie do pliku DB o pojemności 50 GB wymagałoby dużego (2 ^ 8) * (2 ^ 10) = 2 ^ 18 = 256 MB pamięci RAM.
Ale od najnowszych wersji SQLite nie jest to już potrzebne. Przeczytaj więcej tutaj .
źródło
2^18
tak naprawdę to tylko 256 K.Wystąpiły problemy z dużymi plikami sqlite podczas używania polecenia Vacuum.
Nie próbowałem jeszcze funkcji auto_vacuum. Jeśli spodziewasz się często aktualizować i usuwać dane, warto to sprawdzić.
źródło