2009-02-05 20 views
10

Veritabanımda bir Anahtar/değer tablosu tasarlamalıyım ve bunu yapmanın en iyi yolu hakkında rehberlik arıyorum. Temel olarak değerleri dinamik bir adlandırılmış özellik kümesine ilişkilendirebilmem ve bunları bir harici anahtara uygulayabilmem gerekir. Veritabanı tablosundaki Anahtar/Değer çiftleri

Bakmam gereken gerekiyor operasyonlar

şunlardır:

  • Numaralandırma anda aktif anahtarların tüm
  • tüm belirleyin öğelerin bir gruba bir anahtar/değer çifti uygula Verilen bir anahtar için değer olan öğeler Belirli bir anahtarla ilişkilendirilen değerin bazı ölçütlerle eşleştiği tüm öğeleri belirleyin.

O Bunu yapmanın en kolay yolu, bir tablo tanımlamak gibi görünüyor:

CREATE TABLE KeyValue (
    id int, 
    Key varchar..., 
    Value varchar... 
); 

O ben herhangi bir tuşa verilen nedeniyle Anahtar sütundaki çok fazla veri çoğaltma olması muhtemel olduğumu görünüyor Çok sayıda belge için tanımlanmış olması muhtemeldir. Anahtar varchar'ı başka bir tabloya bir tamsayı aramasıyla değiştirmek, bu sorunu gidermektedir (ve etkin anahtarların tümünü numaralandırmak için önemli ölçüde daha verimli hale getirmektedir), ancak bu arama tablosunu sürdürme sorunuyla (beni istediğim zaman içine çekmekte zorlanıyor) Bir özelliği tanımlamak ve bir anahtar/değer temizlendiğinde girişin potansiyel olarak kaldırılması).

Bunu yapmanın en iyi yolu nedir?

cevap

1

Keşfetmeye değer bir seçenek, tabloya yerleştirmeden önce SHA1 veya MD5 kullanarak anahtarı sindirmektir.

Bu, arama tablosundan kurtulmanıza izin verecektir, ancak anahtarlar arasında yineleme yapamayacağınız için yalnızca tek bir yoldan gidersiniz.

1

Bana birkaç tasarım seçeneğiniz olabileceği gibi geliyor.

Seçenek 1: sambo99 belirttiği gibi belki bu değiştirebilir:

keys (
id int not null auto_increment 
key string/int 
hash_code int -- this would be computed by the inserting code, so that lookups would effectively have the id, and you can look them up directly 
) 

values (
id int not null auto_increment -- this column might be nice since your hash_codes might colide, and this will make deletes/updates easier 
key_id int -- this column becomes optional 
hash_code int 
value string/varchar/int... 
) 

-

+0

SHA1 çarpışma olasılığı oldukça fazla 0, çarpışmalara neden olmak için süper kötülük olmanız gerekiyor, eğer süper endişeliyseniz, SHA256 –

+2

'u kullanabiliyorsanız endişeleniyorsanız, DC + 'da bir karma çarpışma (TTH) gördüm. imkansız değil. – erikkallen

5

Eğer

Keys (
id int not null auto_increment 
key string/int 
) 
values (
id int not null auto_increment 
key_id int 
value string/varchar/int 
) 

Seçenek 2 Yanıtınızda ima İki tablo tasarımı Gerekmedikçe bunu optimize etmeyin. Anahtarın ortalama uzunluğu nedir? Bu tablo o kadar büyük olacak ki, naif yolu uygularsanız, sunucunuzun belleğine sığmaz mı? Bunu en basit şekilde uygulamanızı öneririm, performansı ölçün ve sonra yalnızca bir sorun olduğunda sorununuzu yeniden uygulayın.

Performans bir sorunsa, bir tamsayı anahtarını ve ayrı bir tabloyu kullanmak muhtemelen yoldur (tamsayı sütunlarında JOINS, değişken uzunluklu dize sütunları kullanarak JOINS'den genellikle daha hızlıdır). Ancak, optimizasyonun ilk kuralı, ÖNCEDEN ÖNCE OLDUĞUNU, sözde optimize edilmiş kodun aslında işi hızlandırmasını sağladığından emin ol.

+1

+1 basitliği. Performans etkisi açık ve şiddetli olmadıkça, her zaman birlikte çalışmak için en kolay olanı seçin, ardından gerektiği gibi test edin ve optimize edin. –

30

Entity-Attribute-Value adlı bir veritabanı modeli çalıştırıyorsunuz.Bu, anahtar/değer çiftlerini ilişkisel bir veritabanında depolamanın yaygın bir yoludur, ancak veritabanı normalleştirme ve verimliliğine ilişkin bir takım zayıf yönleri vardır.

Evet, gösterdiğiniz tablo tasarımı bunu yapmanın en yaygın yoludur. Bu tasarımda, her varlığın tüm öznitelikleri KeyValue tablonuzda belirgin bir satır alır.

Bir öğe grubuna bir anahtar/değer çifti uygulayın: Gruptaki her öğe için bir satır eklemeniz gerekir.

INSERT INTO KeyValue (id, key, value) VALUES (101, 'color', 'green'); 
INSERT INTO KeyValue (id, key, value) VALUES (102, 'color', 'green'); 
INSERT INTO KeyValue (id, key, value) VALUES (103, 'color', 'green'); 

Ayrıca parametreleri ile INSERT deyimi hazırlamak ve bir döngü ve her yerde öğe kimliği yılların bir numara ile çalışabilir.

Numaralandırma anda aktif tuşların hepsi:

SELECT DISTINCT Key FROM KeyValue; 

Belirli bir anahtar için bir değere sahip tüm öğeleri belirleyin:

SELECT id FROM KeyValue WHERE Key = 'color'; 

tüm belirleyin Belirli bir anahtarla ilişkili değerin bazı ölçütlerle eşleştiği öğeler:

SELECT id FROM KeyValue WHERE Value = 'green'; 

Varlık-Özellik-Değer ile ilgili bazı problemler şunlardır:

  • emin anahtarları yapmak için Hiçbir şekilde tüm öğeler
  • (tüm öğeler için bazı tuşlar zorunlu hale getirmek Hiçbir şekilde aynı yazıldığından yani Geleneksel bir tablo tasarımında NULL DEĞİL.
  • Tüm anahtarlar değer için VARCHAR kullanmalıdır; Anahtar başına farklı veri türleri saklayamaz.
  • Başvuru bütünlüğünü kullanmanın bir yolu yoktur; Bazı anahtarların değerleri için geçerli olan ve başkaları için geçerli olmayan bir FOREIGN KEY yapamaz.

Temel olarak, Varlık Özniteliği Değeri normalleştirilmiş bir veritabanı tasarımı değildir.