1 milyar satır işleme ve sayma için veritabanı tasarımı


10

Gerçek zamanlı GPS verilerini yaklaşık 5000 pr oranında alıyoruz. dakika (4 TCP sunucusundan). Her sunucu, verileri eklemek için tek bir bağlantı kullanır ve ekler arasında veri arabelleğe alır. Her 15 dakikada bir, bir hizmet bu verileri alır ve bunları yolculuklar halinde işler. Yolculuklar oluşturulduktan sonra, gerçek GPS verileri genellikle yalnızca kullanıcı rotayı bir harita üzerinde görmek istiyorsa o kadar önemli değildir.

Sorun, veritabanının eklenen veri hızına yetişmek için mücadele ettiği görülüyor. Bazen yük arttığında, ekleme süresi aniden büyük ölçüde artar (> 30 saniye), bu da daha fazla verinin arabelleğe alınmasına izin verir, bu da daha büyük kesici uçlar ve daha uzun kesici uç süresi ile sonuçlanır.

Mevcut tasarım hakkında bazı yorumlar ve performansı geliştirmek için bazı fikirler ve bazı sorularımıza ve insanların sahip olabileceği diğer ipuçlarına cevap vermeyi umuyorum!

Mevcut Tasarım

Veriler şu anda bir haftayı temsil eden tablolara ayrılmıştır ve bir yıldan eski veriler ikincil bir veritabanında arşivlenmektedir. Her şey, hem ekler hem de okumalar için kullanılan düzenlenebilir bir görünümde birleştirilir.

Masa tasarımı

  • Kimlik (PK, benzersiz tanımlayıcı)
  • DeviceId (FK, int)
  • PersonId (FK, int)
  • VehicleId (FK, int)
  • TokenId (FK, int)
  • UtcTime (PK, tarihsaat2 (3))
  • Enlem (şamandıra)
  • Boylam (şamandıra)
  • Hız (küçük)
  • Başlık (smallint)
  • Uydular (tinyint)
  • IOData (varbiner (100))
  • IgnitionState (tinyint)
  • UserInput (küçük harf)
  • CreateTimeUtc (datetime2 (3))

Endeksler

  • DeviceId_CreateTimeUtc_Desc
  • DeviceId_UtcTime_Desc (Kümelenmiş)
  • PersonId_UtcTime_Desc
  • TokenId_UtcTime_Desc
  • VehicleId_UtcTime_Desc

Endeksler dahil olmak üzere her hafta şu anda yaklaşık 10 GB yer almaktadır ve şu anda ana veritabanında yaklaşık 300 GB veri bulunmaktadır.

Ana veritabanındaki veri tablolarının 1 dosya içeren kendi dosya grupları vardır, ancak ana veritabanındaki diğer tüm tablolarla aynı disktedir. İkincil veritabanı farklı bir diskte, ancak aynı makinede.

Yeni bir tablo bölümü (hafta) kullanıma alındığında, haftalık olarak bir dizin yeniden oluşturma işini de yürüttüğümüzü düşünüyorum. Büzülme yapılmaz.

Makine, 12 GB belleğe sahip 8 çekirdekli bir HP ve ana veritabanını tutan diskte RAID 10 çalışıyor.

fikirler

  • Birincil veritabanında depolanan veri miktarını en fazla 1 ay ile sınırlayın. En azından veritabanını yedekleme / geri yükleme için daha yönetilebilir hale getirir, ancak bunu yaparak bir performans artışı görmeyi bekleyebilir miyiz?
  • Geçerli veriler için dosya grubunda 2 dosya oluşturun ve bunları 2 farklı fiziksel bölüme dağıtın
  • Geçerli verileri tutan master-slave veritabanları oluşturun, böylece ekleme ve okumalar farklı veritabanlarında gerçekleştirilir
  • Geçerli veriler için dosyaları SSD disklere yerleştirin (yansıtma, SSD disklerle herhangi bir performans farkı yaratır mı?)

Daha fazla bilgi gerekiyorsa lütfen bize bildirin. Performansı etkileyen korkunç birçok faktör vardır ve muhtemelen onu ayarlamak için eşit derecede birçok yol vardır.


Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
Paul White 9

Yanıtlar:


8

Dakikada 5000 kesici uç saniyede yaklaşık 83 kesici uçtur. 5 endeks ile saniyede 400 fiziksel satır eklenir. İş yükü bellekte olsaydı, en küçük sunucularda bile sorun yaratmazdı. Bu düşünebildiğim en verimsiz yolu kullanarak satır satır eklemek olsa bile. CPU açısından saniyede 83 önemsiz sorgu ilginç değildir.

Muhtemelen, diske bağlısınız. Bekleme istatistiklerine bakarak ya da doğrulayabilirsiniz STATISTICS IO.

Sorgularınız muhtemelen çok sayıda farklı sayfaya dokunur, böylece arabellek havuzunun tümü için yer kalmaz. Bu, sık sayfa okumalarına ve muhtemelen rastgele disk yazmalarına neden olur.

Sürekli artan bir anahtar nedeniyle yalnızca fiziksel olarak sonuna yerleştirdiğiniz bir tablo düşünün. Çalışma kümesi bir sayfa olacaktır: sonuncusu. Bu, tembel yazar veya denetim noktası işlemi tablonun "son" unu diske yazdığında sıralı GÇ üretecektir.

Rastgele yerleştirilmiş ekleri olan bir tablo düşünün (klasik örnek: bir kılavuz anahtar). Burada, tüm sayfalar çalışma kümesidir, çünkü her ekleme için rastgele bir sayfaya dokunulur. ES'ler rastgele. Çalışma seti söz konusu olduğunda bu en kötü durumdur.

Ortadasın. Dizinleriniz yapıdadır (SomeValue, SequentialDateTime). Birinci bileşen, ikincisinin sağladığı sıralılığı kısmen rasgeleleştirir. Sanırım " SomeValue" için birkaç olası değer var, böylece dizinlerinizde rastgele yerleştirilmiş birçok ekleme noktası var.

Verilerin haftada 10 GB tablolara bölündüğünü söylüyorsunuz. Bu iyi bir başlangıç ​​noktası çünkü çalışma kümesi şimdi 10GB ile sınırlıdır (yapabileceğiniz okumaları dikkate almaz). Ancak 12 GB'lık sunucu belleği ile ilgili tüm sayfaların bellekte kalması pek olası değildir.

Haftalık "bölümlerin" boyutunu küçültebilir veya sunucu belleğini bir miktar artırabilirseniz, muhtemelen iyisinizdir.

Haftanın başında kesici uçların sonunda olduğundan daha hızlı olmasını beklerdim. Bu teoriyi, belirli bir veri boyutunda bir karşılaştırma ölçütü çalıştırarak ve performans tankını görene kadar sunucu belleğini yavaş yavaş azaltarak bir dev sunucusunda test edebilirsiniz.

Artık tüm okuma ve yazma işlemleri belleğe sığsa bile, hala kirli kirli sayfa G / Ç'yi temizleyebilirsiniz. Bundan kurtulmanın tek yolu, dizinlerinizdeki ortak konumlara yazmaktır. Eğer hiç endeksleri çok yardımcı olacak (daha fazla) sıralı anahtarlar kullanmak için dönüştürmek eğer.

Hızlı bir çözüm olarak, istemciler ve ana tablo arasına bir arabellek katmanı eklerdim. Belki bir hazırlama masasına 15 dakikalık yazı biriktirin ve periyodik olarak yıkayın. Bu, yük artışlarını ortadan kaldırır ve büyük masaya yazmak için daha verimli bir plan kullanır.


1
@ usr Çok kapsamlı ve iyi açıklanmış cevap için teşekkürler! Aslında ne kadar bir etki yaratacağını bilmeden sunucu belleğini artırmayı tartıştık - ama şimdi bunu yapmak için gerçekten çok zorlayıcı bir nedenimiz var :) yaklaşık 10000 cihaz kimliği. Evreleme tablosuyla ilgili olarak, öneriniz herhangi bir indeks içermeyen bir tablo mu, ardından her X dakikada bir ana tabloya eklenecek bir iş mi?
sondergard

@usr Reg. kümelenmiş dizini sıralı olarak dönüştürme öneriniz, otomatik inc. kimlik sütununu (tamsayı) seçin ve yalnızca sıralı tutmak amacıyla kümelenmiş dizini bu sütuna değiştirin. Tablolar arasında benzersiz olmaz, ancak birincil anahtar olduğu sürece iyi olmalıyız.
sondergard

1
Evreleme tablosu küçükse ve sorgularınız onunla yaşayabiliyorsa, hiç dizine eklemenize gerek yoktur. Fakat şunları yapabilirsiniz; Stratejilerden biri, CI'yi bir kimlik sütununda yapmaktır (dediğiniz gibi). CI büyükse ve diğer indeksler küçükse bu harikalar yaratabilir. CI yazmaları artık sıralı oldukları için probleminize çok daha az katkıda bulunuyorlar. Bu strateji, anlamlı bir boyut farkı varsa en başarılıdır .; Başka bir fikir, günde bir masa olması olurdu. Belki aylık birleştirme.
usr

Tamam, bu yüzden CI için kimlik sütunu oluşturmaya baktık, ancak maalesef bölümlenmiş bir görünümde mümkün değil (kimlik sütununa izin verilmiyor, varsayılan değerler yok ve tüm sütunlar eke dahil edilmelidir). Belki bir danışman tarafından önerilmesine rağmen, bölümlenmiş görünüm kötü seçilmiş bir tasarımdı
sondergard

2
Yine de, aynı sorunla karşılaşan herkes için, çok sayıda yazma ve sadece birkaç okuma varsa, gerçekten sonuna eklemek ve herhangi bir endekslemeyi ertelemek istiyorsunuz. Öte yandan, hızlı okumalar yapmak ve eklemek için ne kadar zaman aldığınız umurumda değilse, kümelenmiş bir dizine ihtiyacınız vardır.
tiktak
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.