MySQL: birden çok tablo mu yoksa çok sütunlu bir tablo mu?


127

Yani bu daha çok bir tasarım sorusu.

Bir birincil anahtarım var (kullanıcının kimliğini söyleyin) ve bu kullanıcıyla ilişkili tonlarca bilgim var.

Bilgiye göre kategorilere ayrılmış birden çok tablom mu olmalı yoksa çok sütunlu tek bir tablom mu olmalı?

Eskiden bunu yapmak için kullandığım yol, birden çok tabloya sahip olmaktı, örneğin, uygulama kullanım verileri için bir tablo, profil bilgileri için bir tablo, arka uç belirteçleri için bir tablo vb.

Son zamanlarda biri bana bunu bu şekilde yapmamanın daha iyi olduğunu ve çok sayıda sütun içeren bir masanın iyi olduğunu söyledi. Mesele şu ki, tüm bu sütunlar aynı birincil anahtara sahip.

Veritabanı tasarımında oldukça yeniyim, bu nedenle hangi yaklaşım daha iyi ve artıları ve eksileri nelerdir?

Bunu yapmanın geleneksel yolu nedir?


Açıklık getirmek için, yanılıyorsam düzeltin, ancak "çoklu tablolar" bağlantı / ilişkisel tablo olarak anlaşılabilir: en.wikipedia.org/wiki/Associative_entity
cellepo

1
Bu veritabanı analitik amaçlar için veya operasyonel / işlemsel işleme için gerekli mi?
Alexander Radev

Yanıtlar:


113

Herhangi bir zamanda bilgi bire birdir (her kullanıcının bir adı ve şifresi vardır), o zaman muhtemelen bir tabloya sahip olmak daha iyidir, çünkü sonuçları almak için veritabanının yapması gereken birleştirme sayısını azaltır. Bazı veritabanlarının tablo başına sütun sayısında bir sınırlama olduğunu düşünüyorum, ancak normal durumlarda bu konuda endişelenmem ve gerekirse daha sonra her zaman bölebilirsiniz.

Veriler bire çoksa (her kullanıcının binlerce kullanım bilgisi satırı varsa), yinelenen verileri azaltmak için ayrı tablolara bölünmelidir (yinelenen veriler depolama alanını, önbellek alanını boşa harcar ve veritabanının bakımını zorlaştırır. ).

Bunun nedenlerini derinlemesine tartıştığı için veritabanı normalleştirme hakkındaki Wikipedia makalesini ilginç bulabilirsiniz :

Veritabanı normalleştirme, fazlalık ve bağımlılığı en aza indirmek için ilişkisel bir veritabanının alanlarını ve tablolarını düzenleme sürecidir. Normalleştirme genellikle büyük tabloları daha küçük (ve daha az gereksiz) tablolara bölmeyi ve bunlar arasındaki ilişkileri tanımlamayı içerir. Amaç, verileri izole etmektir, böylece bir alana yapılan eklemeler, silmeler ve değişiklikler sadece bir tabloda yapılabilir ve daha sonra tanımlanan ilişkiler aracılığıyla veritabanının geri kalanına yayılabilir.

Normalden arındırma da dikkat edilmesi gereken bir şeydir, çünkü verilerin tekrarlanmasının daha iyi olduğu durumlar vardır (çünkü veri okurken veritabanının yapması gereken iş miktarını azaltır). Başlamak için verilerinizi olabildiğince normalleştirmenizi ve yalnızca belirli sorgulardaki performans sorunlarının farkındaysanız normalleştirmenizi şiddetle tavsiye ederim.


Cevabınız için teşekkürler, bu yüzden okuduktan sonra, bir kullanıcının bire bir sütunlarının olduğu bire bir bilgi durumundan bahsettiğimi düşünüyorum.
Xavier_Ex

@Xavier_Ex - Evet, kullanıcı başına yalnızca bir sütun varsa, o zaman sadece bir büyük kullanıcı tablosuyla çalışmak daha kolay olacaktır (ve DB motorunun optimize etmesi çok daha kolay olacaktır).
Brendan Long

Düzenlediğiniz yayınınız daha yararlı bilgiler sağlar! Bazı sütunların sık sık güncellenmesi durumunda bunları ayrı tablolara koymam gerektiğine dair yeni bir endişem var. Örneğin, bir kullanıcının doğum tarihi hiçbir zaman güncellenmeyecektir, ancak arka uç belirteci bir süre sonra geçersiz kılınabilir ve sık güncelleme gerektirecektir. Performansı artırmak için tabloları bu şekilde ayırsam daha iyi olur mu? Şimdi bahsettiğiniz wiki hakkında bilgi alacağım :)
Xavier_Ex

@Xavier_Ex - Bunu tavsiye etmem. İhtiyacınız olan tüm verilere tek bir tabloda bakabildiğinizde önemli ölçüde daha iyi performans elde edersiniz (normalleştirme makalesine bakın). Birleştirmeler pahalıdır, çünkü (1) dönen bir diskte aramaları da içerebilen birden çok yerde veri aramayı gerektirirler, (2) genellikle birden çok dizin ve bir tür birleştirme gerektirirler ve (3) sorgu planlamayı zorlaştırırlar, ancak bu zor değildir yalnızca zaman alır, ancak aynı zamanda sorgu optimize edicinin bir şeyi yanlış yapma olasılığını da artırır (ve kötü optimize edilmiş sorgular gerçekten yavaş olabilir).
Brendan Long

1
Son zamanlarda aynı sorunla karşılaştım, çünkü MySQL InnoDB tablolarının nispeten küçük bir uzunluk sınırı (~ 8000 bayt) var. Sorun tablomda (çok uzun sigorta formlarından elde edilen veriler, 100'den fazla sütun) hepsi UTF8 olan birden çok varchar sütunumuz var. Böylece ~ 8000 bayt sınırını kolayca doldurduk ve her zaman "depolama motorundan 139 hatası" aldık. Bu yüzden masayı bölmek zorunda kaldık. (Daha yeni Barracuda formatıyla test ettik ve bölünmeden çalıştı, ancak müşterimizin sunucuları hala MySQL 5.0 kullanıyor).
MV.

12

Büyük bir masa genellikle kötü bir seçimdir. İlişkili tablolar, ilişkisel veritabanının birlikte çalışmak üzere tasarlandığı tablolardır. Düzgün bir şekilde dizine eklerseniz ve performanslı sorgular yazmayı bilirseniz, iyi performans göstereceklerdir.

Tablolar çok fazla sütun aldığında, veritabanının bilgileri depoladığı sayfanın gerçek boyutuyla ilgili sorunlarla karşılaşabilirsiniz. Ya kayıt sayfa için çok büyük olabilir, bu durumda kullanıcıları mutsuz eden belirli bir kaydı oluşturamayabilir ya da güncelleyemeyebilirsiniz ya da (en azından SQL Server'da) özellikle bazı taşmalara izin verilebilir. veri türleri (bunu yapıyorsanız bir dizi kuralla birlikte bakmanız gerekir), ancak çok sayıda kayıt sayfa boyutunun dışına taşarsa, çok sayıda performans sorunları yaratabilirsiniz. Şimdi MYSQL'in sayfaları nasıl işlediği ve potansiyel sayfa boyutu çok büyüdüğünde bir sorununuz olup olmadığı, bu veritabanının belgelerine bakmanız gereken bir şeydir.


1
Ah farklı sesler! Bu her zaman harika. Bilgi için teşekkürler! Masalarımı hazırlarken bunun farkında olduğumdan emin olacağım ... ama aslında bu kadar düşük seviyeli şeylerin farkında olmam gerektiğini bilmiyordum.
Xavier_Ex

4

İyi bir örneğim var. Aşağıdaki ilişkiler kümesiyle aşırı Normalleştirilmiş veritabanı:

people -> rel_p2staff -> staff

ve

people -> rel_p2prosp -> prospects

İnsanların isimleri ve kişi ayrıntılarına sahip olduğu, personelin yalnızca personel kaydı ayrıntılarına sahip olduğu, potansiyel müşterilerin yalnızca olasılık ayrıntılarına sahip olduğu ve ilgili tablolar, personel ve olası müşterilerle bağlantı kuran kişilerden gelen yabancı anahtarların bulunduğu ilişki tablolarıdır.

Bu tür bir tasarım tüm veritabanı için devam eder.

Şimdi bu ilişki kümesini sorgulamak, her seferinde çok masalı birleştirme, bazen 8 veya daha fazla tablo birleştirme. 40000 insan kaydını geçtiğimiz için çok yavaşlamaya başladığında, bu yılın ortalarına kadar gayet iyi çalışıyordu.

Endeksleme ve tüm düşük asılı meyveler geçen yıl kullanılmıştı, tüm sorgular mükemmel olacak şekilde optimize edildi. Bu, belirli normalleştirilmiş tasarım için yolun sonudur ve yönetim şimdi 6 aylık bir süre içinde veritabanının yeniden yapılandırılmasının yanı sıra ona bağlı olan tüm uygulamanın yeniden oluşturulmasını onayladı. $$$$ Ah.

Çözelti için doğrudan bir ilişki var olacaktır people -> staffvepeople -> prospect


Yeniden yapılanmanın nasıl gittiğini bilmek ister misiniz? Bir typevarlığınız staffveya bir varlığınız olan tek tablo mirasına benzer bir şey tasarladınız prospectmı?
Coderama

1
Doğrudan ilişki insanlarıyla -> personel ve insan -> potansiyel müşteri ile gitti, cazip çalışıyor, kullanımı kolay, sorgulaması hızlı.
Vlad

4

Bununla karşılaştım ve MySQL'i çok kullanan ve son zamanlarda Postgres'e geçen biri olarak, en büyük avantajlardan biri, Postgres'deki bir alana JSON nesneleri ekleyebilmenizdir.

Dolayısıyla, bu durumda iseniz, çok sayıda sütuna sahip büyük bir tablo arasında karar vermek ve onu bölmek zorunda değilsiniz, ancak sütunları JSON nesnelerine birleştirerek azaltabilirsiniz, örneğin adresin 5 sütun olması yerine, sadece tek ol. Ayrıca bu nesne için de sorgulama yapabilirsiniz.


Peki sorgu sırasında json nesnesini kullanırken performansı ne olacak?
dagalti

1
@dagalti üzerinde kullandığım uygulamalar için performans gayet iyi. Üzerinde kendi kıyaslamamı yapmadım, ancak bu sizin için yararlı olabilir: arangodb.com/2018/02/…
moinhaque

3

Her şeyi tek bir tabloya koyarsanız bu soruları kendinize sorun, o kullanıcı için birden fazla satırınız olacak mı? Bir kullanıcıyı güncellemeniz gerekiyorsa, bir denetim izi tutmak ister misiniz? Kullanıcı bir veri öğesinin birden fazla örneğine sahip olabilir mi? (örneğin telefon numarası gibi) daha sonra bir öğe veya öğe kümesi eklemek isteyebileceğiniz bir durumunuz olacak mı? Evet cevabını verirseniz, büyük olasılıkla yabancı anahtar ilişkileri olan alt tablolara sahip olmak istersiniz.

Üst / alt tabloların avantajları, veri bütünlüğü, dizinler aracılığıyla performans (evet bunu düz bir masada da yapabilirsiniz) ve daha sonra bir alan eklemeniz gerekirse, özellikle gerekli bir alan olacaksa, IMO'nun bakımı daha kolaydır.

Eksileri tasarımı daha zor, sorgular biraz daha karmaşık hale geliyor

Ancak, büyük bir düz masanın uygun olacağı birçok durum vardır, bu nedenle karar vermek için durumunuza bakmanız gerekir.


Bana hatırlattığın için teşekkür ederim! Bu yüzden benim durumumda sadece her kullanıcının birden fazla satıra sahip olamayacağı, dolayısıyla tüm bilgi alanlarının bire bir olduğu durumu düşünüyordum. Ayrıca, bir öğe kavramının birden fazla yerde var olamayacağına inandığım için, kullanıcı aynı öğenin birden fazla örneğine sahip olamaz. Üçüncü soru için, evet tabloya daha fazla unsur ekleyebilirim ama yukarıda bahsettiğim gereksinimleri bozmayacaklar. Birden çok satırı bir kullanıcıyla ilişkilendirmek istediğimde üst / alt tablonun iyi olduğunu düşünüyorum, ancak bu durumda benim endişem, bir kullanıcının bire bir sütunlarının olması.
Xavier_Ex

tüm öğeler şu anda bire bir olsa bile, bu, ana / alt tabloların IMO'suna sahip olma ihtiyacını veya arzusunu ortadan kaldırmaz. Değişen verilerin kaydını tutmak tek kullanımlıktır. tembel yükleme nesneleri başka bir şeydir. tek bir masa yapısının faydaları varken, ebeveyn çocuk düzenleri için de faydalar vardır (yine de insanların bunlarla aşırılıklara gittiğini gördüm).
Brian

1

Zaten bir çeşit veritabanı tasarımı yaptım. benim için veritabanı yönetimi ile sistemin zorluğuna bağlı; evet, yalnızca tek bir yerde benzersiz verilere sahip olmak doğrudur, ancak çok fazla kayıt içeren aşırı normalleştirilmiş veritabanıyla sorgu yapmak gerçekten zordur. Sadece iki şemayı birleştirin; tıpkı facebook, gmail vb. gibi bakımı zor olan çok büyük kayıtlara sahip olacağınızı düşünüyorsanız, büyük bir tablo kullanın. ve basit sistem için bir kayıt kümesi için farklı bir tablo kullanın ... peki bu sadece benim fikrim .. umarım yardımcı olabilir .. sadece yap..yapabilirsin ... :)


1
"Eğer çok büyük kayıtlarınız olacaksa kocaman bir tablo kullanın .." Ancak Facebook, Google kullanıcı verilerini tek bir tabloda saklamaz, onları birçok tablo kadar ayırırlar.
Yami Odymel

0

Bunu yapmanın geleneksel yolu, bir yıldız şeması veya kar tanesi şemasında olduğu gibi farklı tablolar kullanmak olacaktır. Howeevr, bu stratejiyi iki katına dayandırırım. Teoride, verinin yalnızca bir yerde olması gerektiğine inanıyorum, çünkü orada bahsettiğim şema işe yarayacak. Bununla birlikte, raporlama motorları ve BI takımları için sütunsal bir yaklaşımın, raporlama ihtiyaçlarını daha fazla desteklediği için çok faydalı olacağına da inanıyorum. İnfobright.org gibi sütunlu yaklaşımlar, her iki yaklaşımı da inanılmaz derecede yararlı kılan büyük performans kazanımları ve sıkıştırmaya sahiptir. Pek çok şirket, kuruluşta tek bir veritabanı mimarisine sahip olmanın tüm ihtiyaçlarını karşılamadığını fark etmeye başlıyor. Pek çok şirket, birden fazla veritabanı mimarisine sahip olma konseptini uyguluyor.


Bilgi için teşekkürler, ama özür dilerim cevabınızı tam olarak anlayamıyorum ... İlk bahsettiğiniz iki şema üzerinde bir araştırma yapacağım ...
Xavier_Ex

-4

bence tek bir tabloya sahip olmak daha etkili ancak tablonun ilişkiyi, eğilimi ve aynı satırın değişkenlerindeki farkı gösterecek şekilde düzenlendiğinden emin olmalısınız. örneğin, tablo öğrencilerin yaşlarını ve notlarını gösteriyorsa, en yüksek puan alan kişiye en düşük puan alanla iyi bir şekilde farklılaşan ve öğrencilerin yaş farkı eşit olacak şekilde tabloyu düzenlemelisiniz.

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.