Çok büyük veritabanı dosyaları olan sqlite'ın performans özellikleri nelerdir? [kapalı]


325

Ben sqlite desteklenirken bile son derece büyük veritabanı dosyaları ile iyi performans olmadığını biliyorum (sqlite web sitesinde 1GB üzerinde dosya boyutlarına ihtiyacınız varsa bir kurumsal rdbms kullanmayı düşünebilirsiniz belirten bir yorum vardı. artık bulamıyorum, sqlite'ın eski bir sürümüyle ilişkili olabilir).

Ancak, amaçlarım için, diğer çözümleri düşünmeden önce ne kadar kötü olduğu hakkında bir fikir edinmek istiyorum.

2GB'den itibaren çoklu gigabaytlık aralıktaki sqlite veri dosyalarından bahsediyorum. Herkes bu konuda herhangi bir deneyimi var mı? Herhangi bir ipucu / fikir?


1
Diş çekme (diş başına bağlantı) kullanımı sadece okuma için yardımcı olabilir - stackoverflow.com/a/24029046/743263
malkia


23
Yıl 2016: SQLite üzerinde sorunsuz çalışan 5 GB'lık bir veritabanım var. Aynı veri kümesini Postgres'e yükledim. SQLite 2.7 ms, Postgres 2.5 ms karmaşık bir sorgu çalıştırdı. Daha kolay Regex erişimi ve daha iyi dizin özellikleri için Postgres'e son verdim. Ama SQLite beni çok etkiledi ve onu da kullanabilirdim.
Paulb

Yanıtlar:


246

Bu yüzden çok büyük dosyalar için sqlite ile bazı testler yaptım ve bazı sonuçlara vardım (en azından benim özel uygulama için).

Testler, tek bir tablo veya birden çok tablo içeren tek bir sqlite dosyası içerir. Her tabloda yaklaşık 8 sütun, neredeyse tüm tamsayılar ve 4 dizin vardı.

Fikir, sqlite dosyaları yaklaşık 50GB olana kadar yeterli veri eklemekti.

Tekli Masa

Sadece bir tablo ile bir sqlite dosyasına birden çok satır eklemeye çalıştım. Dosya yaklaşık 7GB olduğunda (üzgünüm satır sayıları hakkında kesin olamıyorum) eklemeler çok uzun sürüyordu. Tüm verilerimi ekleme testimin 24 saat kadar süreceğini tahmin etmiştim, ancak 48 saat sonra bile tamamlanmadı.

Bu beni tek, çok büyük bir sqlite tablosunun eklemeler ve muhtemelen diğer işlemler ile ilgili sorunları olacağı sonucuna götürüyor.

Sanırım bu sürpriz değil, tablo büyüdükçe, tüm endekslerin eklenmesi ve güncellenmesi daha uzun sürüyor.

Çoklu Tablolar

Sonra günde bir tablo, birkaç tablo üzerinde zamana göre veri bölme çalıştı. Orijinal 1 tablosu için veriler ~ 700 tabloya bölünmüştür.

Bu kurulumun ekleme ile ilgili bir sorunu yoktu, her gün için yeni bir tablo oluşturulduğundan zaman ilerledikçe daha uzun sürmedi.

Vakum Sorunları

İ_like_caffeine tarafından belirtildiği gibi, VACUUM komutu sqlite dosyası büyüdükçe bir sorundur. Daha fazla ekleme / silme işlemi yapıldıkça, dosyanın diskteki parçalanması daha da kötüleşecektir, bu nedenle amaç dosyayı optimize etmek ve dosya alanını kurtarmak için periyodik olarak VACUUM'dur.

Bununla birlikte, belgelerin işaret ettiği gibi , vakumun tamamlanması için çok uzun zaman alan bir veritabanının tam bir kopyası yapılır. Yani, veritabanı ne kadar küçük olursa, bu işlem o kadar hızlı biter.

Sonuçlar

Özel uygulama için, muhtemelen vakum performansı ve ekleme / silme hızından en iyi şekilde yararlanmak için verileri günde bir tane olmak üzere birkaç db dosyası üzerinde bölerim.

Bu, sorguları karmaşıklaştırır, ancak benim için, bu kadar veriyi endeksleyebilmeye değer bir ödünleşim. Ek bir avantaj, sadece bir günlük değer veri (benim uygulama için ortak bir işlem) bırakmak için tüm bir db dosyasını silebilirsiniz.

Muhtemelen hızın ne zaman sorun haline geleceğini görmek için dosya başına tablo boyutunu izlemem gerekir.

Otomatik vakum dışında artımlı bir vakum yöntemi olmadığı çok kötü . Bunu kullanamıyorum çünkü vakum için hedefim, otomatik vakumun yapmadığı dosyayı (dosya alanı büyük bir anlaşma değil) birleştirmektir. Aslında, belgeler parçalanmayı daha da kötüleştirebileceğini belirtiyor, bu yüzden düzenli olarak dosyada tam bir vakum yapmak zorunda kalıyorum.


5
Çok faydalı bilgiler. Saf spekülasyon ama yeni yedekleme api günlük olarak veritabanınızın parçalı olmayan bir sürümünü oluşturmak için kullanılabilir olup olmadığını merak ve bir VAKUM çalıştırmak için kaçının.
eodonohoe

24
Merak ediyorum, tüm INSERTS'ınız bir işlemde miydi?
Paul Lefebvre

9
Evet, eklemeler işlem başına 10000 mesajlık gruplar halinde yapıldı.
Snazzer

6
Hangi dosya sistemini kullandınız? Ext {2,3,4} ise, veri = ayarı neydi, günlük kaydı etkinleştirildi? İo modellerinin yanı sıra, sqlite'ın diske akması önemli olabilir.
Tobu

5
Ben esas olarak windows üzerinde test edildi, bu yüzden linux davranış hakkında yorum yapamam.
Snazzer

169

Platformumuzda 50 GB + DBS kullanıyoruz. hiçbir şikayet harika çalışıyor. Her şeyi doğru yaptığınızdan emin olun! Önceden tanımlanmış ifadeler mi kullanıyorsunuz? * SQLITE 3.7.3

  1. işlemler
  2. Önceden yapılmış açıklamalar
  3. Bu ayarları uygulayın (DB'yi oluşturduktan hemen sonra)

    PRAGMA main.page_size = 4096;
    PRAGMA main.cache_size=10000;
    PRAGMA main.locking_mode=EXCLUSIVE;
    PRAGMA main.synchronous=NORMAL;
    PRAGMA main.journal_mode=WAL;
    PRAGMA main.cache_size=5000;

Umarım bu başkalarına yardımcı olur, burada harika çalışır


22
Son zamanlarda 160GB aralığında dbs ile test edildi, harika çalışıyor.
Snazzer

10
Ayrıca PRAGMA main.temp_store = MEMORY;.
Vikrant Chaudhary

40
@Alex, neden iki PRAGMA main.cache_size = 5000 ;?
Jack

23
Bu optimizasyonları körü körüne uygulamayın. Özellikle senkron = NORMAL çarpışmalara karşı güvenli değildir. Yani, doğru zamanda bir işlem çökmesi, disk arızaları olmasa bile veritabanınızı bozabilir. sqlite.org/pragma.html#pragma_synchronous
mpm

22
@Alex, bu değerleri ve 'em ile varsayılan değerler arasındaki farkı açıklayabilir misiniz?
4m1nh4j1

65

Fark edilir performans sorunları olmadan 3,5 GB'a kadar SQLite veritabanları oluşturdum. Doğru hatırlıyorsam, SQLite2'nin bazı alt sınırları olabileceğini düşünüyorum, ancak SQLite3'ün böyle bir sorunu olduğunu düşünmüyorum.

Göre SQLite Sınırları sayfasında, her veritabanı sayfanın maksimum boyutu 32 K 'dir. Ve bir veritabanındaki maksimum sayfa sayısı 1024 ^ 3'tür. Yani benim matematiğimle maksimum terapi olarak 32 terabayta çıkıyor. Bence SQLite vurmadan önce dosya sisteminizin sınırlarını vuracaksınız!


3
Hangi işlemleri gerçekleştirdiğinize bağlı olarak, 8G sqlite veritabanında 3000 satır silmeye çalışarak, güzel bir Fransız basını potu demlemek için yeterli zaman alır, ben
benjaminz

4
@benjaminz, yanlış yapıyorsun. Bir işlemde 3 bin satırın silinmesini sararsanız, neredeyse anında olmalıdır. Bu hatayı kendim yaptım: 10k satırları tek tek silmek 30 dakika sürdü. Ama bir kez tüm silme ifadelerini tek bir işleme tamamladım, 5 saniye sürdü.
mvp

55

Eklemelerinizi yapmanın 48 saatten fazla sürmesinin nedeni, dizinlerinizdir. İnanılmaz derecede hızlı:

1 - Tüm dizinleri bırak 2 - Tüm ekleri yap 3 - Tekrar dizin oluştur


23
Bilindiği gibi ... ancak uzun süren bir işlem için, dizinleri yeniden oluşturmak için periyodik olarak bırakmayacaksınız, özellikle de iş yapmak için sorgulayacaksanız. Bu, sqlite db'nin sıfırdan yeniden oluşturulması gerektiğinde, tüm ekler yapıldıktan sonra indekslerin yaratıldığı yaklaşımdır.
Snazzer

24
@Snazzer benzer bir durumda bir "akümülatör" tablosu kullandık: günde bir kez biriken satırları akümülatör tablosundan tek bir işlemle ana tabloya taşıdık. Gerektiğinde bir görünüm her iki tabloyu tek bir tablo olarak sunmaya özen gösterdi.
CAFxX

4
Başka bir seçenek de dizinleri tutmak, ancak eklemeden önce verileri dizin sırasına göre önceden sıralamaktır.
Steven Kryskalla

1
@StevenKryskalla Bu, dizinleri bırakmak ve yeniden oluşturmakla nasıl karşılaştırılır? Karşılaştırıldığını bildiğiniz herhangi bir bağlantı var mı?
mcmillab

1
@mcmillab Bu yıllar önceydi, bu yüzden tüm ayrıntıları veya kıyaslama istatistiklerini hatırlamıyorum, ancak sezgisel olarak düşünerek, rastgele sıralanmış öğeleri bir dizine eklemek O (NlogN) zamanını alırken, N sıralama öğelerini eklemek O (N ) zaman.
Steven Kryskalla

34

Genel tavsiyenin yanı sıra:

  1. Toplu ekleme için bırakma dizini.
  2. Büyük işlemlerde toplu ekler / güncellemeler.
  3. Arabellek önbelleğinizi ayarlayın / günlük / w PRAGMA'larını devre dışı bırakın.
  4. 64 bit makine kullanın (çok sayıda cache ™ kullanabilmek için).
  5. [Temmuz 2014 eklendi] Birden çok SQL sorgusu çalıştırmak yerine ortak tablo ifadesi (CTE) kullanın! SQLite sürüm 3.8.3 gerektirir.

SQLite3 ile yaşadığım deneyimden aşağıdakileri öğrendim:

  1. Maksimum ekleme hızı için herhangi bir sütun kısıtlaması olan şema kullanmayın. (Tabloyu daha sonra gerektiği gibi değiştirin ALTER TABLE ile kısıtlama ekleyemezsiniz).
  2. İhtiyacınız olanı depolamak için şemanızı optimize edin. Bazen bu, tabloları parçalamadan ve / veya veritabanına eklemeden önce verilerinizi sıkıştırmak / dönüştürmek anlamına gelir. Harika bir örnek, IP adreslerini (uzun) tamsayı olarak saklamaktır.
  3. Db dosyası başına bir tablo - kilit çekişmesini en aza indirmek için. ( Tek bir bağlantı nesnesine sahip olmak istiyorsanız, ATTACH DATABASE kullanın .
  4. SQLite, farklı veri türlerini aynı sütunda (dinamik yazma) saklayabilir, bunu kendi yararınıza kullanabilirsiniz.

Soru / yorum hoş geldiniz. ;-)


1
'Db dosyası başına bir tablo' dan ne kadar etki elde ediyorsunuz? Kulağa ilginç geliyor. Sizce tablonuzda sadece 3 masa varsa ve sıfırdan inşa ediliyorsa bunun bir önemi var mı?
Martin Velez

4
@ martin bunu söylemekten nefret eder ama cevap buna bağlıdır . Fikir, verileri yönetilebilir boyuta bölmektir. Kullanım durumumda farklı ana bilgisayarlardan veri topluyorum ve bu yaklaşımın iyi çalıştığı için verilerden sonra raporlar yapıyorum. Başkaları tarafından önerilen tarih / saate göre bölümleme, hayal edebileceğim uzun süreyi kapsayan veriler için iyi çalışmalıdır.
Lester Cheung

3
@Lester Cheung: İkinci # 1'inizle ilgili olarak: SQLite3'ün bu güne kadar tablonun oluşturulmasından sonra ALTER TABLE ile kısıtlama eklemeyi desteklemediğini dokümanlar ve kişisel deneyimlerden anladım. Varolan tablo satırlarına kısıtlama eklemenin veya kaldırmanın tek yolu, istenen özelliklere sahip yeni bir tablo oluşturmak ve tüm satırların üzerine kopyalamaktır; bu, kısıtlamalarla bir kez eklemekten çok daha yavaş olabilir.
Mumbleskates

3
@Widdershins mutlak haklısınız - SQLite'deki ALTER TABLE kısıtlama eklemeye izin vermiyor. Ne içtiğimi bilmiyorum - cevabı güncelleyeceğim - teşekkürler.
Lester Cheung

Bu önerilerin hiçbirinin humongous SQLite db dosyaları kullanarak ilgisi yoktur. Bu cevap gönderildikten sonra soru düzenlendi mi?
A.Rager

9

Ben sqlite ölçeklendirme hakkında ana şikayetleri olduğunu düşünüyorum:

  1. Tek işlem yazma.
  2. Yansıtma yok.
  3. Çoğaltma yok.

9

7GB'lık bir SQLite veritabanım var. Bir iç birleştirme ile belirli bir sorgu gerçekleştirmek için 2.6s alır Bu hızlandırmak için dizinleri eklemeyi denedim. Hangi dizin (ler) i eklediğime bağlı olarak, bazen sorgu 0,1 saniyeye, bazen de 7 saniyeye kadar yükseldi. Benim durumumda sorun, bir sütun son derece yinelenen bir dizin eklemek performansı düşürdüğünü düşünüyorum :(


9
Birçok kopyaya sahip bir sütun neden performansı düşürür (ciddi soru)?
Martin Velez

6
düşük kardinaliteye sahip bir sütunun dizine eklenmesi daha zordur: stackoverflow.com/questions/2113181/…
metrix

9

SQLite belgelerinde, bir veritabanı dosyasının pratik boyut sınırının birkaç düzine GB: s olduğuna dair bir ifade vardı. Bunun nedeni, SQLite'ın bir işlem başlattığınızda "kirli sayfaların bitmap'lerini ayırması" gerekliliğiydi. Bu nedenle, veritabanındaki her MB için 256 bayt RAM gerekiyordu. 50 GB'lik bir DB dosyasına yerleştirmek için ağır (2 ^ 8) * (2 ^ 10) = 2 ^ 18 = 256 MB RAM gerekir.

Ancak, SQLite'ın son sürümlerinden itibaren, buna artık gerek yoktur. Daha fazlasını buradan okuyun .


25
Bunu belirtmek zorunda olduğum için çok üzgünüm, ama 2^18aslında sadece 256 K.
Gabriel Schreiber

7
@GabrielSchreiber ve ayrıca 50GB (2 ^ 10) MB değil, bu sadece 1GB. Yani 50GB bir veritabanı için 12.5MB belleğe ihtiyacınız var: (2 ^ 8) * (2 ^ 10) * 50
elipoultorak

8

Vacuum komutunu kullanırken büyük sqlite dosyalarıyla sorun yaşadım.

Henüz auto_vacuum özelliğini denemedim. Verileri sık sık güncellemeyi ve silmeyi bekliyorsanız, bu göz atmaya değer.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.