Bir normalize veritabanı şeması verilere erişmek için en iyi yolu nedir?

5 Cevap php

Ben normalize veritabanları ile geliyor tutar bir sorun var ve en iyi çözüm arıyordu.

Ben bir albüm bilgileri veritabanı var herhalde. Ben bir normalize moda kurulum şema istiyorum, bu yüzden kurulum iki tablo - albümleri, albüm içerdiği tüm şarkıları listeler tek her albüm için liste ve şarkıları vardır.

albums
------
aid
name

songs
-----
aid
sid
length

Bir albüm şarkı herhangi bir sayı içerebilir gibi bu kurulum, normalleştirilmiş bir şekilde veri depolamak için iyidir. Ancak, sezgisel bir şekilde veri erişim artık çok daha zor hale gelmiştir. Sadece tek bir albüm üzerinde bilgi kapmak sorgu basit, ama nasıl bir zamanlar tek bir sorguda birden fazla albüm kapmak mı?

Şimdiye kadar, ben ile geldi iyi cevabı yardımı ile gruplama ve diziler gibi şarkılar bilgisini dönüştürmektedir. Örneğin, sonuç bu gibi bir şey olacaktır:

aid, sids,      lengths
1,   [1, 2],    [1:04, 5:45]
2,   [3, 4, 5], [3:30, 4:30, 5:30]

Ben verilerle çalışmak istiyorsanız, o zaman bir anlamsız egzersiz gibi görünüyor SID ve uzunlukları, ayrıştırmak zorunda: Ben sadece bunları daha sonra ayırmak için db değerleri bir demet bağlamak yapıyorum.

Sorum: şemanın bu tür bir veritabanına erişmek için en iyi yolu nedir? Birden diziler ile şaşırıp? Ben yerine birden diziler sahip, tek bir diziye bir nesne ve daha sonra bu şarkıları bir şarkının bilgilerinin tamamını saklamak gerekir? Veya resultset (sonsuz katılmak çeşit), şarkı N sayısını karşılamak için sütun keyfi bir sayı ekleyerek bir yolu var mı? Ben en iyi veri erişim konusunda herhangi bir fikir açığım.

Bu sorguları sık sık çalıştırmak olacak gibi ben de verimlilik konusunda endişeliyim.

Herhangi bir fark yaparsa, ben bir PHP ön uç ile birlikte bir PostgreSQL db kullanıyorum.

5 Cevap

Ben zorluk noktası görme var. Eğer "nasıl bir kerede tek bir sorguda birden fazla albüm kapmak etmeyin" ile tam olarak ne demek istiyorsunuz? Eğer zorluklar Tam olarak ne ile var?

Sezgisel söyleyebilirim:

SELECT
  a.aid    album_id,
  a.name   album_name,
  s.sid    song_id,
  s.name   song_name,
  s.length song_length
FROM
  albums a
  INNER JOIN songs s ON a.aid = s.aid
WHERE
  a.aid IN (1, 2, 3)

ve

SELECT
  a.aid         album_id,
  a.name        album_name,
  COUNT(s.sid)  count_songs,
  SUM(s.length) sum_length   /* assuming you store an integer seconds value  */
FROM                         /* here, not a string containing '3:18' or such */
  albums a
  INNER JOIN songs s ON a.aid = s.aid
WHERE
  a.aid IN (1, 2, 3)
GROUP BY
  a.aid

Eğer / ekran bilmek istediğinize bağlı. Ya toplu bilgiler için veritabanı sorgulamak, ya da size app sorgu sonucu # 1 üzerinden kendiniz hesaplayabilirsiniz.

Depending on how much data is cached in your app, ve how long queries take the one strategy can be faster than the other. I would recommend querying the DB, though. DBs are made for this kind of stuff.

Seni anlıyorum, ama tekrarlanan verilerin bir çok ile sona çünkü, ilk sorgu ile sorunları var - albüm adı birçok kez tekrarlanır. Benim pasta var ve çok, onu yemeye çalışıyorum - Ben veri mümkün olduğunca sıkı olmak istiyorum, ama bu agrega olmadan gerçekçi değil.

Ah, şimdi sorunuzu anlıyorum. Sen en iyi nasıl çoğu için aslında çok pahalı değil mikro-optimize şey soruyorsun. Ve ile oynuyor demektir çözüm aslında önemli ölçüde daha az verimli onu çözmeye çalışıyor "sorun" daha olacak.

Benim tavsiyem tabloları katılmak ve ihtiyacınız sütunları dönmek olacaktır. 10.000 'den az kayıtlar döndürülür şey için, her şarkı kaydı ile bu albumName geri teslim için önemli bir tel zaman cezası fark etmez.

Eğer alanda yavaş yavaş performans fark ederseniz, o zaman optimize. Ama akıllı bir sürü insan "tabloları birleştirmek ve ne gerek dönmek" çözüm hızlı araştırma yapma konusunda 50 yıl geçirdim unutmayın. Ben size ev haddelenmiş dize birleştirme / de-birleştirme stratejisi ile yeneceğim şüpheliyim.

Ben tekrarlanan veri ile 10 sütun var olsa bile, bu uygulamada gerçekten bir performans darboğazı olması muhtemel olduğunu düşünüyorum sürece Jason KESTER katılıyorum. Veri tekrarlanan bu kesme peşinde iseniz Ancak, o zaman ben 2 sorguları kullanarak önereceğiz:

Query #1:

SELECT sid, length     -- And whatever other per-song fields you want
FROM songs
ORDER BY aid

Query #2:

SELECT aid, a.name, COUNT(*)
FROM albums a
JOIN songs s USING (aid)
GROUP BY aid, a.name
ORDER BY aid, a.name

İkinci sorgu uygun bölümler halinde ilk sorgunun çıktı kırmak sağlar. Eğer herhangi bir değişiklik bu iki sorgular arasındaki tabloya yapılan olacağını varsayabiliriz eğer bu sadece güvenilir çalışacağını unutmayın - aksi takdirde SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ile bir işlem gerekir.

Yine, iki ayrı sorguları kullanarak olduğunuz gerçeği çoğu durumda iki katına ağ gecikme + sorgu ayrıştırma + sorgu planlama ağ verimi de etkili bir artış bataklık olma ihtimali olduğu gibi bu yavaş genel yapmak olasıdır. Ama en azından tekrarlanan veri gönderme bu pis korkunç bir his var olmaz ... :)

Katılmak sorgular, tablolar birlikte koymak için veritabanını sormak kimlikleri uyan ve tek bir tablo dönecektir. Bu şekilde veri dinamik geçerli görev, sigara normalleştirilmiş veritabanları yapamayacağı bir şey için yapılandırılabilir.

Bunun için normalleşmesini kırmak olmaz. Tablolar normailsed bırakın ve daha sonra kullanmak sorgulamak için aşağıdaki - http://stackoverflow.com/questions/43870/how-to-concatenate-strings-of-a-string-field-in-a-postgresql-group-by-query