Bir veritabanı şema tasarımı için bazı öneri Need

7 Cevap php

Ben (ölçeklenebilirlik açısından) sistemi bir çok (işlevsellik açısından) basit ama zor tasarlarken kullanıcıların nerede birbirlerine mesaj olabilir. Çok basit bir sohbet hizmeti olarak düşünün. Bir kullanıcı bir php sayfası aracılığıyla bir mesaj ekleyebilirsiniz. Mesaj kısa ve bir alıcı adı vardır.

Başka bir php sayfasında, kullanıcı ona bir defada gönderilir ve sonra veritabanında onları siler tüm iletileri görebilirsiniz. İşte bu. Yani, bu sistem için gereken tüm işlevselliği. Nasıl (görünümünde bir veritabanı / php noktasından) bu tasarımı hakkında gitmeli?

Şimdiye kadar böyle tablo var:

  • alan1 -> mesaj (varchar)
  • field2 -> alıcı (varchar)

Şimdi sql insert için, ben alır zaman veritabanında bağımsız satır sayısı sabit olduğunu bulmak. Yani benim send.php iyi bir getiri garantisi zamanınız olacak.

Ama mesajlar aşağı çekmek için, benim pull.php uzun satır sayısı arttıkça alacak! Ben sql seçmek bulmak (ve silme) satırlar büyüdükçe daha uzun sürer ve bu ben bile sonra doğrudur added an index for the recipient field.

Basitçe onların mesajları php çekti önce, kullanıcıların daha uzun bir süre beklemek zorunda kalacak durumda ise şimdi, o zaman tamam olurdu. Ama ne ben endişeliyim her pull.php hizmet süresi gerçekten uzun sürüyor zaman, php sunucu bazı isteğine bağlantıları reddetmesine başlayacak olmasıdır. Ya da daha kötüsü, sunucu sadece ölebilir.

Yani soru o terazi bu tür tasarımı nasıl, nedir? Herhangi bir ipucu / püf noktaları?

PS. Numaraları bazı estiamte:

  • kullanıcı sayısı 50,000 ile başlar ve yukarı gider.
  • ortalama her kullanıcı diğer bitmeden saklanan yaklaşık 10 mesajınız var aşağı çekme olabilir.
  • Her kullanıcı etrafında 10-20 mesajları bir gün gönderir.


Bugüne kadar cevapları okuyarak GÜNCELLEME:

Ben sadece pull.php az iletileri aşağı çekerek yardımcı olmadığını açıklığa kavuşturmak istiyorum. Hatta sadece tablo büyük olduğunda bir mesaj bir uzun zaman alacaktır çekin. Böyle bir seçme yapmak zorunda tablo tüm iletileri sahip olmasıdır:

select message from DB where recipient = 'John'

Bu onu değiştirmek bile çok yardımcı olmuyor

select top 1 message from DB where recipient = 'John'

Şimdiye kadar cevaplardan o select O (n) ya da biraz daha iyi, onun etrafında hiçbir şekilde olacak yavaş tablo daha uzun gibi görünüyor. Bu durumda, nasıl php taraftan bu ele gerekir? Kullanıcı karışık olması ve daha da kötü yapar deli gibi ferahlatıcı sona erecek, çünkü ben php sayfası http başarısız istemiyorum.

7 Cevap

Eğer önermek gibi bunun için veritabanı tasarımı basittir. Bildiğim kadarıyla bir kez kullanıcı daha fazla mesaj var daha uzun alarak, ne yapabilirim sadece sonuçları sayfalandırmak olduğunu. Mantıklı ve sadece bu kayıtları çekmek ne olursa olsun ilk 10/50/100 göster ya. Genel olarak, sizin kat magnatude veya daha fazla bir emriyle mesajları artar hacmi sürece çok artırmak gerekir. Sen bir saniyeden daha kısa bir şekilde tekrar 1000 kısa mesaj çekmek gerekir. Şimdi bu noktada görüntülemek için sayfa için daha fazla zaman alabilir, ama sayfalama yardımcı nereye şu olabilir.

Ama buna dayanarak aracılığıyla ve gelecekteki özellikleri düşünme olacak ve biraz daha dışarı veritabanı oluşturmaya öneririm. Yazılım daha fazla özellik ekleyerek veritabanı nispeten zor değişiyor, kolaydır.

Lütfen alıcı için VARCHAR kullanmayın. Bunu yapmak için en iyi bir Recipient table with a primary key Bu bir tamsayı (ya da insanların son derece büyük miktarlarda bekliyoruz bigint).

Sonra seçin ifadeleri yaptığınızda:

SELECT message FROM DB WHERE recipient = 52;

Hız geri alınmasına satırlar çok daha hızlı olacaktır.

Artı, ben çoğu durumda O (log n) olduğu, MySQL indeksler B-Trees olduğuna inanıyoruz.

Bir dizinin olmayan bir veritabanı tablo bile n sayı olmak üzere bir 'nerede' yan tümcesi, bir yığın için büyük o notasyonu O (n) ile değerlendirilen tablonun her satırında bir yığın sonuçları sorgulama, bir yığın denir Tablodaki satırları. O bir karmaşıklığı tablodaki eşleşen satır bulmak için (log (n)) sonuçları (ve bu gerçekten veritabanı motoru yatan etkene bağlıdır) bir dizin ekleme. İndeks kesinlikle bir şekilde bir B-ağacı tür uygulanan olmasıdır. Hatta bir dizin varken, tabloya satır ekleme O (1) bir işlemdir.

 > But for pulling down messages, my pull.php will take longer as the number of rows 
 increase! I find the sql select (and delete) will take longer as the rows grow and
 this is true even after I have added an index for the recipient field.

Eğer bir dizin ortasına eklediğiniz SÜRECE, hangi noktada veritabanı motoru yerleştirmek için aşağı satır kayması gerekir. Eğer dizinden sildiğinizde aynı oluşur. Endeksin birden fazla tür var unutmayın. Kullandığınız endeks daha fazla veri elenmiş ve ekler ile taşınmalıdır olarak kümelenmiş bir dizin değil ve siler emin olun.

Sineklik Mesajlarınızı resmi anlamda ilişkisel değil çünkü RDBMS'yi kullanmayın sizin için mevcut en iyi seçenek ... vermiştir. Bir dosya sisteminden çok daha iyi performans alırsınız.

dbarker da doğru cevaplar verdi. O 3 kez aşağı olarak neden bilmiyorum, ama ben puan kaybedebilir risk onu oylayacak. dbarker "Dikey Partisyonlama'ya" atıfta ve onun önerisi kabul ve good hem de. Bu roket ameliyat insanlar değildir.

Benim önerim, RDBMS'niz işlevsellik bu tür uygulamak bunu seçme, güncelleme, ekleme hatırlıyorum yaparsanız, tablodaki sayfalarındaki tüm yer kilitleri silmek değil etmektir. Eğer bir veritabanına bu işlevselliği koyarak ile ileri gitmek yaparsanız eşzamanlılık artırmak için bir platform mevcut ise, o zaman bir nolock kilit ipucu ile seçer çalıştırın. Eğer bu kadar çok sayıda eşzamanlı kullanıcı varsa Ayrıca, dbarker önerilen dikey bölüm tabloları ve I / O eşzamanlılık artırmak için ayrı sürücü (sadece hacimleri fakat ayrı donanım) bu veritabanı dosyaları yerleştirin.

Yani soru o terazi bu tür tasarımı nasıl, nedir? Herhangi bir ipucu / püf noktaları?

Evet, Message Queuing için bir ilişkisel veritabanı kullanmak istemiyorum. Ne yapmaya çalışıyorsun, bir ilişkisel veritabanı iyi için tasarlanmış ne değildir, ve bunu olurken, onun tür bir tornavida ile bir çivi sürüş gibi.

Bunun yerine, SecondLife de adamlar onlardan bir çok yorumlanan düzgün bir wiki var, orada pek çok açık kaynak kodlu mesaj kuyruklardan birine bakmak.

http://wiki.secondlife.com/wiki/Message_Queue_Evaluation_Notes

Daha mesajları istenen olanları bulmak için daha fazla zaman - Bu kaçınılmaz bir sorundur. Yapabileceğiniz tek şey, zaten ne yaptığını n - sayıdır kümelenmiş bir dizin bakmak için ((u log) + m) O tarayabilirsiniz tam bir tablo için zamana bakmak bir indeks eklemek ve (n) O çevirin toplam mesajları, u kullanıcı sayısı ve kullanıcı başına mesajların sayısını m.

Lütfen pull.php herhangi bir anda gösterecektir satır sayısını sınırlayın.

Aktarmak fazla veri, o kadar uzun olursa olsun DB ne kadar büyük, sayfayı görüntülemek için alacaktır.

Sen, SQL veri sınırı en son N satırları döndürmek gerekir.

EDIT Put an index on Recipient and it will speed it up. You'll need another column to distinguish rows if you want to take the top 50 or something, possibly SendDate or an auto incrementing field. A Clustered index will slow down inserts, so use a regular index there.

Sen her zaman kullanıcı başına tek bir satır var ve sadece tek bir uzun kayıt içine araya mesajları bağlamak olabilir. Eğer uzun bir süre için mesajlarınızı tutuyor ediyorsanız, o gitmek için en iyi yol değildir, ama bir tek bulmak için sorunu azaltır ve depolama süresi ve saati almak tek bir find at bağlamak. Daha ayrıntıya girmeden söylemek zor - ne DB Tasarım sert yapar iyi tehlikeye şekilde sistemin tüm hedefleri toplantı parçasıdır. Tüm detaylar olmadan, onun sert iyi uzlaşma tavsiye vermek.

EDIT: Ben bu konuda oldukça açık, ama besbelli değil sanıyordum: o okuduğunda, bir okuyucunun kuyruğunu kesme sürece Bunu yapmak olmaz. Ben açıklama istendiğinde nedeni budur.