Her ürünün birçok parametresi olduğu birçok ürün türü için bir ürün tablosu nasıl tasarlanır


140

Masa tasarımı konusunda fazla deneyimim yok. Amacım, aşağıdaki gereksinimleri karşılayan bir veya daha fazla ürün tablosu oluşturmaktır:

  • Birçok ürün türünü (TV, Telefon, PC, ...) destekleyin. Her ürün çeşidinin farklı bir parametre seti vardır, örneğin:

    • Telefon Renk, Boyut, Ağırlık, İşletim Sistemi ...

    • PC'de CPU, HDD, RAM olacak ...

  • Parametre seti dinamik olmalıdır. İstediğiniz parametreyi ekleyebilir veya düzenleyebilirsiniz.

Her ürün için ayrı bir masa olmadan bu gereksinimleri nasıl karşılayabilirim?

Yanıtlar:


233

Açıkladığınız tür hiyerarşisini modellemek için en az şu beş seçeneğiniz vardır:

  • Tek Tablo Devralma : tüm Ürün türleri için tek bir tablo, tüm türlerin tüm niteliklerini depolamak için yeterli sütun. Bu , herhangi bir satırda çoğu NULL olan birçok sütun anlamına gelir .

  • Sınıf Tablosu Devralma : Tüm ürün türlerinde ortak olan öznitelikleri saklayan Ürünler için bir tablo. Ardından, ürün türü başına bir tablo, söz konusu ürün türüne özgü nitelikleri depolar.

  • Beton Tablo Kalıtım : Ortak Ürün özellikleri için tablo yok. Bunun yerine, ürün türü başına bir tablo, hem yaygın ürün özelliklerini hem de ürüne özgü özellikleri depolar.

  • Serialized LOB : Tüm ürün türlerinde ortak olan özellikleri depolayan Ürünler için bir tablo. Fazladan bir sütun, yarı yapılandırılmış verilerden oluşan bir BLOB'u XML, YAML, JSON veya başka bir biçimde saklar. Bu BLOB, her ürün türüne özgü özellikleri depolamanızı sağlar. Bunu tanımlamak için Cephe ve Memento gibi süslü Tasarım Desenleri kullanabilirsiniz. Ancak, SQL içinde kolayca sorgulanamayan nitelikler bloğuna bakılmaksızın; tüm blob'u uygulamaya geri getirip orada sıralamanız gerekir.

  • Varlık Öznitelik Değeri : Ürünler için bir tablo ve öznitelikleri sütunlar yerine satırlara döndüren bir tablo. EAV ilişkisel paradigma açısından geçerli bir tasarım değildir, ancak birçok kişi yine de kullanır. Bu, başka bir cevapta belirtilen "Özellikler Kalıbı" dır. Bazı tuzaklar için StackOverflow'daki eav etiketi ile ilgili diğer soruları görün .

Bu konuyla ilgili daha fazla yazdım, Genişletilebilir Veri Modelleme .


EAV hakkında ek düşünceler: Birçok kişi EAV'yi destekliyor gibi görünse de, sevmiyorum. En esnek çözüm ve bu nedenle en iyisi gibi görünüyor. Ancak TANSTAAFL atasözünü unutmayın . İşte EAV'in bazı dezavantajları:

  • Bir sütunu zorunlu hale getirmenin bir yolu (eşdeğeri NOT NULL).
  • Girişleri doğrulamak için SQL veri türlerini kullanmanın bir yolu yoktur.
  • Özellik adlarının tutarlı bir şekilde yazıldığından emin olmanın bir yolu yoktur.
  • Herhangi bir özelliğin değerlerine yabancı anahtar koymanın bir yolu yoktur; örneğin, bir arama tablosu için.
  • Geleneksel bir tablo düzeninde sonuçları getirmek karmaşık ve pahalıdır, çünkü JOINher bir özellik için birden fazla satırdan özellik almak için yapmanız gerekir .

EAV'ın sağladığı esneklik derecesi, diğer alanlarda fedakarlık gerektirir, muhtemelen kodunuzu orijinal sorunu daha geleneksel bir şekilde çözmek için olduğundan daha karmaşık (veya daha kötü) yapar.

Ve çoğu durumda, bu esnekliğe sahip olmak gereksizdir. OP'nin ürün türleri hakkındaki sorusunda, ürüne özgü özellikler için ürün türü başına bir tablo oluşturmak çok daha basittir, bu nedenle en azından aynı ürün türündeki girişler için uygulanan bazı tutarlı yapılarınız vardır.

EAV'ı yalnızca her satırın potansiyel olarak farklı özelliklere sahip olmasına izin verilmesi gerekiyorsa kullanırım . Sonlu bir ürün türü kümeniz olduğunda, EAV aşırıya kaçar. Sınıf Tablosu Kalıtım benim ilk tercihim olurdu.


Güncelleme 2019: JSON'u "birçok özel özellik" sorununa çözüm olarak kullanan insanların sayısı ne kadar fazla olursa, bu çözümü o kadar az beğenirim. Sorguları desteklemek için özel JSON işlevlerini kullanırken bile sorguları çok karmaşık hale getirir . Normal satırlarda ve sütunlarda depolamak yerine JSON belgelerini depolamak çok daha fazla depolama alanı gerektirir.

Temel olarak, bu çözümlerin hiçbiri ilişkisel bir veritabanında kolay veya verimli değildir. "Değişken niteliklere" sahip olma fikri temel olarak ilişkisel teori ile çelişmektedir.

Bunun nedeni , uygulamanız için en az kötü olan çözümlerden birini seçmeniz gerektiğidir . Bu nedenle, bir veritabanı tasarımı seçmeden önce verileri nasıl sorgulayacağınızı bilmeniz gerekir. "En iyi" bir çözüm seçmenin bir yolu yoktur, çünkü belirli bir uygulama için çözümlerden herhangi biri en iyisi olabilir.


11
@HimalayaGarg Option "4.5", Bill'in gönderisinin tam anlamıyla tersidir.
user3308043

2
MySQL'in aksine, SQL Server XML, XPath ve XQuery için geniş bir desteğe sahiptir. Bu nedenle, SQL Server kullanıcıları için en iyi seçenek, XML türündeki bir sütunda (seçenek 4) ekstra öznitelikleri saklamak olacaktır. Bu şekilde "tüm blob'u uygulamaya geri getirip orada sıralamak zorunda kalmazsınız." SQL Server'daki XML sütunlarında bile dizinler oluşturabilirsiniz.
Delphi.Boy


2
Benim durumum için Serialized LOB'u tercih ederim. Peki ORM için uygun mudur? EF kullanıyorum.
Mahmood Jenami

@ user2741577, elbette, ancak LOB'den yapılandırılmamış veri alanlarını açmak ve bunları ORM nesnenizin her varlık alanına uygulamak için muhtemelen özel kod yazmanız gerekecektir. EF bilmiyorum, ancak bunu yapan bir temel ORM sınıfı oluşturabileceğinizi düşünüyorum. Veritabanı satırının somut alanlarından hangi alanların ve LOB alanlarından hangi alanların geldiğini izlemeniz gerekir, böylece nesneyi kaydetme zamanı geldiğinde bir LOB'u yeniden oluşturabilirsiniz.
Bill Karwin

12

@Taş kalp

Burada sonuna kadar EAV ve MVC ile giderdim.

@Billy Karvin

İşte EAV'in bazı dezavantajları:

  • Bir sütunu zorunlu hale getirmenin bir yolu yoktur (NOT NULL değerine eşdeğer).
  • Girişleri doğrulamak için SQL veri türlerini kullanmanın bir yolu yoktur.
  • Özellik adlarının tutarlı bir şekilde yazıldığından emin olmanın bir yolu yoktur.
  • Herhangi bir özelliğin değerlerine yabancı anahtar koymanın bir yolu yoktur; örneğin, bir arama tablosu için.

Burada bahsettiğiniz tüm şeyler:

  • veri doğrulama
  • özellik adları yazım denetimi
  • zorunlu sütunlar / alanlar
  • bağımlı niteliklerin yok edilmesiyle başa çıkmak

Bence hiçbir veri tabanına ait değil çünkü hiçbir veri tabanı bu etkileşimleri ve gereksinimleri bir uygulamanın programlama dili gibi uygun bir seviyede ele alamıyor.

Bence bir veritabanı bu şekilde kullanmak, bir çivi çekiçlemek için bir kaya kullanmak gibidir. Bir kaya ile yapabilirsiniz, ancak daha hassas ve bu tür etkinlikler için özel olarak tasarlanmış bir çekiç kullanmanız gerekmiyor mu?

Geleneksel bir sekmeli düzende sonuçları getirmek karmaşık ve pahalıdır, çünkü birden çok satırdan öznitelik almak için her öznitelik için JOIN yapmanız gerekir.

Bu sorun, kısmi verilerle ilgili birkaç sorgu yapılarak ve uygulamanızla birlikte tablo şeklinde düzenlenerek çözülebilir. 600 GB ürün verileriniz olsa bile, bu tablodaki her satırdan verilere ihtiyacınız varsa bunları toplu olarak işleyebilirsiniz.

Daha ileri gitmek Sorguların performansını artırmak isterseniz, örneğin raporlama veya genel metin araması gibi belirli işlemleri seçebilir ve bunlar için gerekli verileri depolayacak ve periyodik olarak yeniden oluşturulacak dizin tablolarını hazırlayabilirsiniz, her 30 dakikada bir diyelim.

Her gün daha ucuz ve daha ucuz hale geldiğinden fazladan veri depolama maliyetiyle ilgilenmenize bile gerek yok.

Uygulama tarafından yapılan işlemlerin performansıyla hala ilgileniyorsanız, verileri önceden işlemek ve daha sonra sadece ana uygulamanızda optimize edilmiş verileri işlemek için Erlang, C ++, Go Language kullanabilirsiniz.


you can always use Erlang, C++, Go Language to pre-process the dataNe demek istedin? DB yerine Go lang? Lütfen bunu biraz açıklayabilir misiniz?
Yeşil

1
Tamamen katılıyorum. EAV gitmek için bir yoldur, özellikle db şema değişiklikleri olmadan yeni tür ürünler ve parametreler eklemenize izin verecek esneklik seviyesine ihtiyacınız varsa, yani başvurunuz aracılığıyla üretimde yaşamak. Orada bulundum, bitti. Benim için çalıştı. Yavaş sorgular hakkında ... burada kimse önbellekleri duydu mu? ;)
pawel.kalisz

@Yeşil daha net hale getirmek için son paragrafı düzenledim, ancak ham EAV verilerinizi veri dönüşümleri, bir ağaç yapısındaki aramalar veya herhangi bir temel harita ile başa çıkabilen bir işlemde gerçekten hızlı bir şekilde azaltmak ve bellek etkin bir şekilde. Buradaki ayrıntılar neyin optimize edilmesi gerektiğine bağlı olacaktır
Pawel Barcik

6

Eğer Class Table Inheritanceanlam kullanırsam :

Ürünler için tek bir tablo, tüm ürün türlerinde ortak olan özellikleri saklama. Ardından, ürün türü başına bir tablo, söz konusu ürün türüne özgü nitelikleri depolar. Fatura Karwin

Bu da Bill Karwin'in önerilerini en iyi şekilde sevdim.

Yalnızca 1 tür için ortak olan, daha sonra 2, sonra 3, vb. İçin ortak olan bir özellik olduğunda hangi acil durum planına sahip olmalıyım?

Örneğin: (bu benim gerçek sorunum değil, sadece bir örnek)

Mobilya satarsak, sandalye, lamba, kanepe, TV vb. Satabiliriz. TV tipi, taşıdığımız güç tüketimi olan tek tip olabilir. Ben power_consumptionözniteliği tv_type_table. Ama sonra bir power_consumptionözelliği olan Ev sinema sistemlerini de taşımaya başlıyoruz . Tamam, bu sadece bir diğer ürün, bu yüzden de bu alana ekleyeceğim, stereo_type_tableçünkü bu noktada muhtemelen en kolay. Ancak zamanla daha fazla elektronik taşımaya başladığımızda power_consumption, bunun olması gerektiği kadar geniş olduğunu fark ediyoruz main_product_table. Ben şimdi ne yapmalıyım?

Alanı main_product_table. Elektronik döngü için bir komut dosyası yazın ve her birinden doğru değeri koymak type_tableiçin main_product_table. Sonra her bir sütunu bırakın type_table.

Şimdi her zaman aynı GetProductDatasınıfı kullanarak ürün bilgilerini çekmek için veritabanı ile etkileşim; koddaki herhangi bir değişikliğin şimdi yeniden düzenlenmesi gerekiyorsa, bunlar yalnızca bu Sınıfa ait olmalıdır.


3

Ürün tablonuz ve 3 sütunlu ayrı bir ProductAdditionInfo tablonuz olabilir: ürün kimliği, ek bilgi adı, ek bilgi değeri. Renk, her türlü Ürün tarafından olmasa da birçok ürün tarafından kullanılıyorsa, Ürün tablosunda boş değerli bir sütun olabilir veya yalnızca ProductAdditionalInfo öğesine yerleştirebilirsiniz.

Bu yaklaşım, ilişkisel bir veritabanı için geleneksel bir teknik değildir, ancak pratikte çok kullanıldığını gördüm. Esnek olabilir ve iyi bir performansa sahip olabilir.

Steve Yegge bunu Özellikler kalıbı olarak adlandırıyor ve kullanımı hakkında uzun bir yazı yazdı.


4
Özellikler Kalıbı, başka bir adla yalnızca Varlık-Öznitelik-Değeri'dir. Yaygın olarak kullanılır, ancak ilişkisel bir veritabanında saklanması normalleştirme kurallarını ihlal eder.
Bill Karwin

2
Dürüst olmak gerekirse, @Bills cevabında EAV açıklamasını okuduğumda ne açıkladığını tam olarak anlamadım. Ama dediğin zaman 3 columns: product ID, additional info name, additional info valuekavramı anladım. Aslında bunu daha önce yaptım ve problemlerle karşılaştım. Ancak şu anda bu sorunların ne olduğunu hatırlamıyorum.
JD Isaacks

1
@JDIsaacks Bu modelde, ortak bir sorun, tüm nitelikleri almak için kaç JOIN'e ihtiyacımız olduğunu bilmememizdir.
Omid
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.