100+ GB tablolarda düzenli olarak çok yönlü birleşimler yapmak için MySQL kullanılsın mı?


11

Arka plan :
Makul bir şekilde ölçeklendirmek istediğim bir web uygulaması oluşturdum. Google veya Twitter olmadığımı biliyorum, ancak uygulamam her kullanıcı için oldukça büyük miktarda veri kullanıyor ve bu nedenle oldukça yüksek veri gereksinimleri var. Daha sonra her şeyi yeniden tasarlamak zorunda kalmadan makul derecede iyi ölçeklendirmeye hazır olmak istiyorum.

Kendimi bir veritabanı uzmanı değil, bir yazılım geliştiricisi olarak görüyorum. Bu yüzden buraya gönderiyorum. Umarım çok daha fazla veritabanı uzmanlığına sahip biri bana tavsiyelerde bulunabilir.

Nispeten çok sayıda kullanıcıyla, ancak Facebook numaraları gibi bir şey olmadan, şöyle bir DB olmasını bekliyorum:

Bir "Büyük masa":

  • 250 milyon kayıt
  • 20 sütun
  • Yaklaşık 100 GB veri
  • Endeksli bigint (20) yabancı anahtar var
  • Dizine alınmış bir varchar (500) string_id sütunu var
  • İnt (11) "değer" sütununa sahiptir

Diğer 4 tablo:

  • Her biri 10 milyon kayıt
  • Her biri yaklaşık 2 - 4 GB veri
  • bu tabloların her birinde 4 - 8 sütun bulunur
  • bir sütun datetime date_created
  • bir sütun varchar (500) string_id sütunudur
  • bu tabloların her birinden bir veya iki sütun bir birleştirmede seçilecektir

Bu tablolardan biri ortalamaları depolamak için kullanılır - şeması bigint (20) id, varchar (20) string_id, datetime date_created, float average_value

Ne yapmak istiyorum - iki nispeten pahalı sorgu:

  1. Yeni ortalama değerleri hesapla:

    • Yabancı anahtar kullanarak büyük tablodan birkaç milyona kadar ayrı kayıt seçin.
    • String_id öğesine göre gruplayarak yeni bir ortalama hesaplayın.
    • Sonuçları ortalamalar tablosuna ekleyin.
    • Şu anda oluşturulduğu gibi, bu sorgu iki birleşim kullanır.
  2. Sunum yapan kullanıcılar için normalleştirilmemiş, salt okunur kayıtlar oluşturun:

    • Büyük tablodan 1.000-40.000 kayıt arasından seçim yapmak için yabancı bir anahtar kullanın.
    • Dize kimliği sütunu ile en yeni kayıttaki diğer dört tablonun her birine katılın.
    • Sonuçları normalleştirilmemiş bir tabloya ekleyin.
    • Bu kayıtlar kullanıcılara bilgi görüntülemek için kullanıcı arabirimi tarafından kullanılır.
    • Şu anda oluşturulduğu gibi, bu sorgu dört birleşim kullanır.

Bu pahalı sorguların her birini, sonuçlarını kullanıcılardan gelen istekleri işleyen gerçek zamanlı bir ön uç DB sunucusuna gönderecek bir toplu iş arka uç veritabanında çalıştırmayı planlıyorum. Bu sorgular düzenli aralıklarla çalıştırılacaktır. Ne sıklıkta karar vermedim. Ortalama sorgu günde bir kez yapılabilir. Normalleştirmeyi kaldır sorgusunun daha sık olması gerekir - belki birkaç dakikada bir.

Bu sorguların her biri şu anda MySQL'de birkaç saniye içinde çok büyük bir makinede “büyük tabloda” 100K kayıtlı bir veri kümesiyle çalışır. Hem ölçeklendirme yeteneğim hem de ölçeklemenin maliyeti konusunda endişeliyim.

Sorular :

  1. Bu yaklaşım kulağa hoş geliyor mu? Büyük resim açısından açıkça yanlış olan bir şey var mı?
  2. RDBMS doğru araç mı, yoksa Hadoop ailesindeki bir şey gibi diğer "büyük veri" çözümlerine mi bakmalıyım? Eğilimim RDBMS kullanmaktır çünkü veriler yapılandırılmıştır ve ilişkisel modele güzelce uyar. Yine de belli bir noktada, artık bir RDBMS kullanamayacağım anlaşılıyor. Bu doğru mu? Bu anahtar ne zaman gereklidir?
  3. Çalışacak mı? Bu sorgular makul bir sürede çalıştırılabilir mi? Sorgu # 1 için belki de saat bekleyebilirim, ancak # 2 numaralı sorgu dakikalar içinde bitmelidir.
  4. Donanım açısından nelere dikkat etmeliyim? RAM ve CPU darboğazlarım nelerdir? Dizinleri RAM'de tutmanın önemli olduğunu düşünüyorum. Dikkate almam gereken başka bir şey var mı?
  5. Bir noktada muhtemelen verilerimi bölümlere ayırıp birden çok sunucu kullanmam gerekecek. Kullanım durumum zaten bu kategorideymiş gibi mi görünüyor yoksa tek bir makineyi bir süre dikey olarak ölçeklendirebilecek miyim? Bu veriler 10 kat daha fazla olacak mı? 100x?

Bunu iyice cevaplamak zor. Belki genel olarak MySQL sorgu performans özellikleri hakkında araştırma yapmaktan daha iyidir, bu yüzden ne beklediğinizi bilirsiniz .; Tabii ki her zaman yapabileceğiniz bir şey sunucuya 20 disk koymak böylece 3GB / s ya da öylesine okuyabilirsiniz. Ama sadece kapsamlı bir yazılım yanıtının peşindesiniz.
usr

Yanıtlar:


4

Daha fazla veri biriktirmeyi ve karşılaştırmayı denediniz mi? 100K satır önemsizdir. Darboğazları ele almanız ve nerede olduğunu görmeniz gerektiğini düşündüğünüz gibi 250M veya 500M'yi deneyin.

Bir RDBMS, sınırlamalara dikkat ederseniz ve sistemin güçlü yanlarıyla çalışırsanız çok şey yapabilir. Bazı şeylerde son derece iyi ve diğerlerinde korkunçlar, bu yüzden doğru uygun olduğundan emin olmak için denemeniz gerekecek.

Bazı toplu işlem işleri için, düz dosyaları yenemez, verileri RAM'e yükleyemez, bir dizi döngü ve geçici değişken kullanarak onu parçalayabilir ve sonuçları dışarı atamazsınız. MySQL asla bu tür bir hıza uymayacak, ancak doğru ayarlanmış ve doğru kullanılırsa büyüklük sırasına girebilir.

Yapmak isteyeceğiniz şey, verilerinizin nasıl bölümlenebileceğini araştırmaktır. Birbirine ayıramayacak kadar çapraz bağlanma yolunda çok fazla veri içeren büyük bir veri kümeniz var mı veya bölümlemek için doğal yerler var mı? Eğer bunu bölümleyebiliyorsanız, bir sıra yığın içeren bir tablonuz olmayacaktır, ancak potansiyel olarak çok daha küçük olan bir masanız olacaktır. Daha küçük indekslere sahip daha küçük tablolar daha iyi performans gösterir.

Donanım açısından, platformunuzun nasıl performans gösterdiğini test etmeniz gerekir. Bazen hafıza şarttır. Diğer zamanlarda disk G / Ç. Bu gerçekten verilerle ne yaptığınıza bağlıdır. CPU kullanımınıza çok dikkat etmeniz ve sorunun nerede olduğunu bilmek için yüksek düzeyde IO beklemeniz gerekir.

Mümkün olduğunda verilerinizi birden fazla sisteme bölün. Cesur hissediyorsanız MySQL Kümesi'ni kullanabilir veya her birinin mantıklı bir bölümleme şeması kullanarak tüm veri kümesinin rastgele bir bölümünü sakladığı birçok bağımsız MySQL örneğini döndürebilirsiniz.


@tadman Tavsiyeniz için teşekkürler. Aslında denemenin yerini tutacağının farkındayım. 250M sıralarıyla karşılaştırmadım çünkü ilk önce yaklaşımımla ilgili açıkça yanlış bir şey olmadığından emin olmak istedim. Kulağa gelmemiş gibi geliyor. Buna ek olarak, bu kadar veri elde etmek ve bunu biraz gerçekçi bir şekilde yapmak henüz nasıl çözüleceğini çözemediğim bir sorundur. Verileri bölümlere ayırmanın bazı potansiyel yolları var. Sanırım daha sonra sadece verilerimi
artırmayı

1

Özet Tablolar.

Her gün, günün verileri için toplu bilgileri hesaplayın. Bunu "özet" tablolarına ekleyin. Sorgularınızı onlara karşı yapın. 10 kat daha hızlı.

Daha fazla tartışma için lütfen sağlayın

  • MASA OLUŞTURMA TABLOSU (şu anda olduğu gibi)
  • Masa boyutları (bahsettiğiniz)
  • Önerilen SELECT'ler

Bazı bariz şeyler ...

  • BIGINT nadiren garanti altındadır. 8 bayt alır. INT UNSIGNED 4 alır ve 0..4billion değerlerine izin verir. Ve MEDIUMINT vb. Var.
  • 'Olgu' tablosundaki birden çok dizin, özellikle INSERT'ler için genellikle ciddi bir performans sorunudur. Orada sorun mu yaşıyorsunuz?
  • DATETIME 8 bayttır; TIMESTAMP 4'tür
  • Açık FOREIGN KEY CONSTRAINTS güzel, ama pahalı
  • JOIN'ler bir performans sorunu olabilir veya olmayabilir; SELECT ve CREATE'leri görmeniz gerekir.
  • 100GB, 'büyük' ​​bir MySQL veritabanı için güzel bir boyuttur; Ben Hadoop, vb olmadan çalışmak için yapılmış olabilir şüpheli Şimdi böyle bir db ile anlaşma - veri oldukça dahil olmasına rağmen çoğu UI sayfaları bir saniyenin altında cevap.
  • Bir noktada verileri 'temizleyecek misiniz'? (Bu, BÖLME için ana kullanım durumuna yol açar.)

"Daha küçük -> daha önbelleğe alınabilir -> daha hızlı


0

Ön uç verilerinizi sunmak için, her zaman kesici uçlar ve gob'ler yoksa, arka uçla senkronize tutulan ancak verileri sunmak için optimize edilmiş materyalize görünümlere eklemek için tetikleyicileri kullanarak gerçekten dövemezsiniz. Tabii ki, bu tetikleyicilerdeki birleşmeleri vb. Minimumda tutmanız gerekir. Kullandığım bir strateji, bu ekleri / güncellemeleri bir ara tabloya sıralamak ve daha sonra her dakika veya daha sonra göndermektir. 4 GB kayıtlardan bir kayıt göndermek çok daha kolaydır. Aradığınız kayıtları hızlı bir şekilde bulabilseniz bile 4 GB veri akışı uzun sürüyor.

Tadman'a katılıyorum. En iyisi, istediğiniz sistem türünde beklediğiniz veri türüyle profil oluşturmaktır.


Benim yazımda bahsettiğim gibi, görünümler on milyonlarca kayıt içeren tablolarda dört birleşim kullanan bir sorguya bağlıdır, bu yüzden gerçekten bir görünümün nasıl yardımcı olacağını görmüyorum.
xnickmx

Tetikleyiciler bu boyut veritabanı için yeterince hızlı olmayabilir. Saniyede kaç tane INSERT oluyor?
Rick James

1
@xnickmx Çok fazla ekleme / güncelleme yoksa, tetikleyiciler normalleştirilmemiş verileri senkronize etmeyi kolaylaştırır. Ekler / güncellemeler için daha hızlı gitmesi gerekiyorsa, bunları şu şekilde sıralayın : blog.shlomoid.com/2008/04/… veya kendiniz pişirin. Bu şekilde, yeni verileri almak için mevcut 100 milyon satır tablosuna katılmak zorunda kalmazsınız, çünkü tetikleme tetiklendiğinde, yeni verileri tam olarak bildiğiniz gerçeğinden faydalanırsınız ve sadece tx'in bir parçası olarak denormalize edebilirsiniz. veya daha sonra denormalizasyon için sıraya alabilir.
wes.stueve

@RickJames Kabul Edildi. Bu tür bir strateji için eklerin miktarını ve ne kadar hızlı işlemeleri gerektiğini dikkate almalısınız.
wes.stueve
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.