Veritabanı yeniden tasarım fırsatı: Bu sensör veri toplama için hangi tablo tasarımı kullanılacak?


13

Arka fon

Her biri 10 dakikalık aralıklarla topladığımız yaklaşık 100 veri noktasına sahip yaklaşık 2000 sensörlü bir ağım var. Bu veri noktaları genellikle int değerleridir, ancak bazıları dize ve kayan değerdir. Bu veriler 90 gün boyunca saklanmalıdır, mümkünse daha fazla ve yine de verimli olmalıdır.

Veri tabanı tasarımı

Başlangıçta bu projeyle görevlendirildiğinde, her sensör için virgülle ayrılmış dosyalar yazan bir C # uygulaması yazdım. O zamanlar çok fazla değildi, birileri trendlere bakmak istediğinde, csv'yi Excel'de açıp gerektiği gibi grafik çizerdik.

İşler büyüdü ve MySQL veritabanına geçtik. Her sensör için bir tablo oluşturdum (evet biliyorum, birçok tablo!); iyi çalışıyor, ancak bazı sınırlamaları var. Bu kadar çok tablo ile, belirli bir değer ararken tüm sensörler arasında veri bulan bir sorgu yazmak kesinlikle mümkün değildir.

Bir sonraki sürümde Microsoft SQL Server Express'e geçtim ve tüm sensör verilerini büyük bir tabloya yerleştirdim. Bu da işe yarar ve ilgilenilen tüm sensörler arasında değerler bulmak için sorgular yapmamıza izin verir. Ancak, Express sürümü için 10GB sınırına girdim ve SQL Server Standard'a yatırım yapmak yerine MySQL'e geri dönmeye karar verdim.

Soru

MySQL performansından ve ölçeklenebilirliğinden memnunum, ancak hepsi bir arada veriler tablosuna bağlı kalmanın en iyisi olup olmadığından emin değilim. Tek bir tabloda 10GB farklı bir tasarım istiyor gibi görünüyor. Ben grafik için veri sorgulama ihtiyacı hala orada olduğunu belirtmek gerekir, ve ben tam 90 gün boyunca bir sensör için sıcaklık verileri, örneğin grafik bir sorgu için performans sorunları olacağını endişeliyim. (Başka bir deyişle, grafik, ilgilenilen sensörü izole etmek için SQL veri yığınları arasında sıralamayı beklemeden, hızlı bir şekilde üretilmelidir.)

Performansı artırmak için bu tabloyu bir şekilde ayırmalı mıyım? Yoksa böyle büyük bir masaya sahip olmak sıra dışı değil mi?

Ben hemen hemen herhangi bir sorgu için tanımlayan sınırları olan Sensor ID ve Timestamp sütunlarında dizinler var. (yani sensör X için A zamanından B zamanına kadar veri alın).

Parçalama ve bölümleme hakkında biraz okudum, ama bu durumda bunların uygun olduğunu hissetmiyorum.


Düzenle:

Şimdiye kadar yapılan yorumlara ve cevaplara dayanarak, bazı ek bilgiler yardımcı olabilir:

Belirsiz Depolama Değil: Şu anda 90 gün boyunca veri depolamıyorum. Günlük olarak, 90 günden eski verileri kaldıran bir sorgu çalıştırıyorum. Gelecekte önemli hale gelirse, daha fazla depolayacağım, ancak şimdilik yeterli. Bu, boyutun kontrol ve performansının yüksek kalmasına yardımcı olur (er).

Motor Türü: MyISAM kullanılan orijinal MySQL uygulaması. Bu kez yeni uygulama için tablolar oluştururken (birçok yerine bir veri tablosu) varsayılan olarak InnoDB'ye ayarlamışlardır. Birine ya da diğerine gereksinimim olduğuna inanmıyorum.

Normalleştirme: Veri toplama tablosunun yanında elbette başka tablolar da vardır. Bu destek tabloları, sensörler için ağ bilgileri, kullanıcılar için giriş bilgileri, vb. Gibi şeyleri saklar. Normalleştirilecek çok şey yoktur (bildiğim kadarıyla). Veri tablosunun bu kadar çok sütuna sahip olmasının nedeni, her sensörden çok sayıda değişken olmasıdır. (Çoklu sıcaklıklar, ışık seviyeleri, hava basıncı, vb.) Bana normalleştirme, fazladan veri veya tekrar eden grup olmadığı anlamına gelir. (En azından 1NF için.) Belirli bir sensör için, tüm değerleri belirli bir zamanda saklamak için bir veri satırı gerekir ve orada 1: N ilişki yoktur (gördüğüm).

Tabloyu işlevsel olarak parçalayabilirim (örneğin) bir tablodaki tüm sıcaklıkla ilgili değerleri ve başka bir tablodaki tüm hava basıncıyla ilgili değerleri yapabilirim. Bu, yalnızca sıcaklık sorgusu yapan biri için verimliliği artırabilir, ancak yine de tüm verileri bir kerede eklemek zorundayım. Yine de, verimlilik kazancı SELECT operasyonları için faydalı olabilir. Açıkçası kullanıcıların verileri ne sıklıkta istediklerine bağlı olarak tabloyu dikey olarak ayırmak daha iyi olur. Belki de tüm yapmam gereken budur. Sanırım soruyu sorduğumda, bunu yapmanın faydalı olacağına dair bir onay arıyorum.


Düzenleme 2:

Veri Kullanımı: Nihayetinde verilerin çoğuna asla bakılmaz veya ihtiyaç duyulmaz, çünkü genellikle yalnızca sorunlu öğelere odaklanırız. Ancak, sorunları bulmaya çalışırken , verileri aramak ve hangi öğelerin yakınlaştırılacağını belirlemek için çeşitli araçlar kullanırız.

Örneğin, bellek kullanım değeri (müşteriye özel tescilli bir yazılım programı) ile yeniden başlatma / çökme arasında bir ilişki olduğunu fark ettik. Topladığım veri noktalarından biri bu bellek kullanımı ile ilgilidir ve belirli bir bellek kullanımı aşıldıktan sonra cihazların kararsız hale geldiğini göstermek için geçmiş verilerine bakabildim. Bugün, bu yazılımı çalıştıran cihazların alt kümesi için bu değeri kontrol ediyorum ve çok yüksekse yeniden başlatma komutu veriyorum. Bu keşfedilene kadar, bu verilerin toplanmasının değerli olduğunu düşünmedim.

Bu nedenle, değer şüpheli olsa bile, bazı 100 veri noktasının toplanmasını ve saklanmasını sağladım. Ancak normal günlük kullanımda, kullanıcılar genellikle bu parametreleri bir düzine inceler. Bir kullanıcı belirli bir coğrafi alanla ilgilenirse, (yazılım kullanarak) belki birkaç düzine sensör için grafikler veya veri tabloları oluşturabilir. Sıcaklık, hava basıncı ve ışık seviyeleri gibi şeyleri gösteren iki veya üç çizim çizgisine sahip 30 günlük bir grafiğe bakmak nadir değildir. Bunu yapmak şuna benzer bir sorgu çalıştırır:

SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);

(Her sensörün kendi tablosuna sahip olduğu orijinal MySQL sürümünde, üç ayrı sorgu yayınlanır, ancak sonuçlar grafiği oluşturmak için yazılımda birleştirilir.)

Çünkü dataTablo çok sayıda satır (~ 10 milyon), ilgili indislerine sahip olmasına rağmen idve data_timestampperformans (bu örnek ile bir saniyeden daha kısa karşı 4500 satır 9 saniye içinde geri) çok tablolu senaryoya göre özellikle kötüdür. Hangi tabloların belirli kriterleri karşıladığını bulma yeteneği, çoklu tablo şemasında pratik olarak sıfırdır ve bu nedenle tek bir tabloya geçmenin nedeni.

Bu tür sorgu, farklı veri gruplarını seçtikleri ve her sonuçtaki grafikleri karşılaştırdıklarından, birden çok kullanıcı tarafından hızlı bir şekilde arka arkaya yapılabilir. Grafik veya elektronik tablo başına yaklaşık 10 saniye beklemek oldukça sinir bozucu olabilir.

Veriler 90 gün sonra atılır. Arşivlenebilir, ancak şu anda bir gereklilik değildir.

Umarım bu bilgiler verilerin toplanmasından ve depolanmasından sonra nasıl kullanıldığını daha iyi göstermeye yardımcı olur.


Bu sorunun doğru cevabı alması için muhtemelen verilerin gerçekte nasıl kullanıldığını genişletmelisiniz. Şimdiye kadar verdiğiniz bilgilerin derinliğindeki eğrinin önündesiniz, ancak sorunuzu yanlış açıdan soruyor olabilirsiniz.
Mark Storey-Smith

İyi bir nokta, @ Mark, ben de bu konuyu biraz açıklayacağım. Çok uzun bir süredir korkacağından korkmamam gerekiyordu.
JYelton

Yanıtlar:


5

Büyük bir nedenden ötürü tabloyu bölümlere ayırmayı düşünmelisiniz.

Dev bir tabloda bulunan tüm dizinler, yalnızca bir dizin bile, INSERT'leri, UPDATE'leri ve DELETE'leri yürütürken dizin bakımını gerçekleştirmek için çok fazla CPU yükü ve disk G / Ç üretebilir.

Tablo Bölümleme'nin neden büyük bir yardım olacağına dair 7 Ekim 2011 tarihinde daha eski bir yazı yazdım . İşte benim geçmiş yazıdan bir alıntı:

Verilerin bölümlenmesi, aynı sınıfta mantıksal ve uyumlu olan verileri gruplandırmaya hizmet etmelidir. Veriler doğru bir şekilde gruplandığı sürece, her bir bölümü arama performansının ana husus olması gerekmez. Mantıksal bölümlemeye ulaştıktan sonra arama süresine konsantre olun. Verileri yalnızca kimliğe göre ayırıyorsanız, okuma veya yazma işlemleri için birçok veri satırına asla erişilemeyebilir. Şimdi, bu önemli bir husus olmalı: En sık erişilen tüm kimlikleri bulun ve bölümleyin. Daha az sıklıkta erişilen tüm kimlikler, 'mavi ay içinde bir kez' sorgusu için dizin aramasıyla erişilebilen büyük bir arşiv tablosunda bulunmalıdır.

Bu yazının tamamını daha sonra okuyabilirsiniz .

Takip etmek için 10GB tablonuzda hangi verilerin nadiren kullanıldığını araştırmanız ve bulmanız gerekir. Bu veriler, tarihsel bir doğa için geçici sorgulara ihtiyacınız olduğunda kolayca erişilebilen bir arşiv tablosuna yerleştirilmelidir. Bu OPTIMIZE TABLEarşivin 10 GB'den, ardından 10 GB tablosundan geçirilmesi, SELECT, INSERT, UPDATE ve DELETE'leri çalıştırmak için daha hızlı bir Çalışma Kümesiyle sonuçlanabilir. DDL bile 2GB'lık bir Çalışma Setinde 10GB'lık bir tablodan daha hızlı gidecektir.

GÜNCELLEME 2012-02-24 16:19 EDT

Dikkate alınması gereken iki nokta

  1. Yorumunuzdan, normalleştirme ihtiyacınız olan şey gibi görünüyor.
  2. 90 günden eski olan her şeyi bir arşiv tablosuna taşımanız gerekebilir, ancak yine de aynı anda arşiv ve çalışma kümesine erişebilirsiniz. Verileriniz tamamen MyISAM ise, MERGE depolama motorunu kullanmanızı öneririm. İlk olarak, bir çalışma kümesi MyISAM tablosunu ve bir arşiv MyISAM tablosunu birleştiren bir kez MERGE tablo haritasını oluşturursunuz. Verileri bir MyISAM tablosunda 91 günden az tutacak ve 90 günden eski verileri arşive taşıyacaksınız. Yalnızca MERGE tablo haritasını sorgulayabilirsiniz.

İşte nasıl kullanılacağına dair iki yazı:

İşte çok sütun içeren tablolarda yaptığım ek bir yazı

MySQL'de çok fazla sütun var


Daha az ihtiyaç duyulan sütunlar vardır, ancak tüm sensörler yaklaşık aynı oranda dikkat çeker. Böylece, masayı dikey olarak bölmenin avantajlı olacağını hayal edebiliyorum. Örneğin, 20 sütunlu bir tablo (sık erişilen) ve 80 sütunlu bir tablo (nadiren erişilen). Bunun bölümleme ile aynı şey olduğundan emin değilim.
JYelton

Düzenleme için teşekkürler. "MySQL'de çok fazla sütun" hakkındaki yazınızı okudum. Sorumu faydalı olabilecek bazı ek noktalarla düzenleyeceğim.
JYelton

5

İlginç ... Eğer tüm sensörler aynı tür veriler üretiyorsa, hepsini aynı tabloya koymak mantıklıdır, ancak bu miktarda veriyle neden performans konusunda endişelendiğinizi görebiliyorum.

Bir grafik ürettiğiniz 90 günlük normal süre midir? Öyleyse, iki tablonuz olabilir: 90 gün (veya biraz gevşeklik istiyorsanız) bugüne kadar olan verileri depolayan ana sensör veri tablosu ve bundan daha eski olan her şey arşiv tablosuna gider. Bu, raporların oluşturulmaya başlandığı tablonun boyutunu azaltmaya yardımcı olabilir ve umarım 10 GB'lık verilerinizin çoğunluğu ana tabloda değil arşiv tablosunda olacaktır. Arşivleme işi gece çalışacak şekilde zamanlanabilir.

Ayrıca, verileri rapor oluşturmak için daha iyi bir yapıda saklayan ayrı bir raporlama veritabanı oluşturmayı da düşünün (sorguladığınız şeyle daha yakından eşleşecek şekilde tasarlanmış tablolar ve belki de uzun süre alacak değerleri önceden hesaplayın ve toplayın mümkünse ana veritabanından düzenli olarak (her gece gibi) yeniden doldurun. Tabii ki, en güncel verilerden oluşturulan raporlara ihtiyacınız varsa, bu işe yaramayabilir.


Bu noktada 90 günden fazla bir şey saklamak gerekli değildir, ancak iyi olur. Bir "arşiv" tablosunda saklamak en iyisidir. Grafikler ve veri analizi sadece saatler ile tam 90 gün arasında değişmektedir. Çoğu grafik isteği yalnızca geçen haftayı kullanır, ancak 90 günlük grafikler yaygındır. Firmamız (henüz) daha uzun rapor talep etmemiştir.
JYelton

@JYelton: Bu yaklaşımda istediğiniz kadar katmana sahip olabilirsiniz. En güncel tablo yalnızca Bugün'den olabilir. Bir sonraki tablo bugünden 2 hafta öncesine kadar olabilir. Bir sonraki tablo Bugün'den 90 gün öncesine kadar olabilir. Son tablo HERŞEY olabilir.
Hayal kırıklığına

Seni doğru anlarsam, tabloyu çoğaltmayı söylüyorsunuz, ancak farklı zaman aralığı kapsamlarıyla. Birisi 7 günlük bir rapor isterse, sadece bir hafta geriye giden bir tablo kullanılır. Daha sonra 8 güne kadar genişlerse, bir sonraki en büyük tablo (örneğin 30 gün) kullanılır mı? Bu kesinlikle kısa süreli sorguların hızını artıracaktır, ancak katmanlı tablolarla (ucuz değil) ilgilenmek için depolama (ucuz) ve programlama mantığı pahasına olacaktır.
JYelton

@JYelton: Evet, sanırım doğru anladın. Sorgu zaman aralığı aralıkları standartsa (bugün - 1 gün, bugün - 7 gün, bugün - 30 gün, bugün - 90 gün), o zaman hangi tabloya her zaman bileceğinizden çok zor olacağını düşünmüyorum çarptı. Zaman aralıkları, aralığın başlangıcının geçerli tarih olmayabileceği farklı uzunluklarda olabilirse, uygulama mantığının zorlaşacağı ve çapraz tabloların birden çok tablodaki UNION işlemleriyle pahalı olabileceği sorgularının doğru olacağı doğrudur.
FrustratedWithFormsDesigner
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.