Envanter öğeleri değişen özelliklere sahip olduğunda envanter veritabanı yapısı


10

Kurumsal donanım bilgilerini depolamak için bir envanter veritabanı oluşturuyorum. Veritabanı, iş istasyonları, dizüstü bilgisayarlar, anahtarlar, yönlendiriciler, cep telefonları, vb menzil izler. Birincil anahtar olarak aygıt seri numaraları kullanıyorum. Yaşadığım sorun, bu aygıtlar için diğer özniteliklerin farklı olması ve envanter tablosunda diğer aygıtlarla ilgisi olmayan alanlara sahip olmak istemiyorum. Aşağıda, veritabanının bir kısmının ERD'sine bir bağlantı bulunmaktadır (bazı FK ilişkileri gösterilmemiştir). Örneğin, iş istasyonu aygıt türüne sahip bir aygıt telefon tablosuna konamaz bu yüzden kurmaya çalışıyorum. Bu, cihaz türünü veya sınıfını doğrulamak için birçok tetikleyicinin kullanılmasını gerektiriyor gibi görünüyor ve farklı özelliklere sahip farklı bir cihaz her zaman izlenecek yeni tablolar;

ERD1

Seri numaralarına eşlenebilen öznitelik tabloları oluşturmaya baktım, ancak bir aygıta atanan aygıt türüne uygulanmayan özniteliklerin aygıta atanmasına izin verdim, örneğin, birisi isterse bir iş istasyonuna bir telefon numarası özniteliği atayabilir . Bu sitede aşağıdaki yapıyı veren bir açıklama buldum:

Widget Örneği ERD

Özniteliklerin tümü depoladığım öğeler için geçerli olsaydı bu yapı harika olurdu. Örneğin, veritabanı yalnızca cep telefonları saklıyorsa, özellikler dokunmatik ekran, izleme dörtgeni, klavye, 4G, 3G ... gibi şeyler olabilir. Bu durumda, hepsi telefonlara uygulanır. Veritabanım, yalnızca belirli türdeki aygıtlar için geçerli olan hostname, circuitType, phoneNumber gibi özelliklere sahip olacaktır.

Sadece belirli bir aygıt türüne uygulanan özniteliklerin bu tür bir aygıta atanabilmesi için ayarlamak istiyorum. Bu veritabanını nasıl kuracağınıza dair herhangi bir öneriniz var mı? Bunun bire bir ilişkilerin doğru kullanımı olup olmadığından veya bunu yapmanın daha iyi bir yolu olup olmadığından emin değilim. Buna bakmak için zaman ayırdığınız için şimdiden teşekkür ederiz.

İşte okuduğum diğer konulardan bazıları. Bana iyi bir fikir verdiler, ama gerçekten uygulandıklarını sanmıyorum:

/programming/9335548/how-to-structure-database-for-inventory-of-unlike-items

/programming/1249632/database-structure-for-items-with-varying-attributes

/programming/5559587/product-inventory-with-multiple-attributes

/programming/6613802/question-about-setting-up-inventory-database

/programming/514111/how-to-best-represent-items-with-variable-of-attributes-in-a-database

Yanıtlar:


6

Süpertip / Alt tür

Supertype / subtype modeline bakmaya ne dersiniz? Ortak sütunlar bir üst tabloya gider. Her farklı türün, kendi PK'si olarak üst öğenin kimliğiyle kendi tablosu vardır ve tüm alt türlerde ortak olmayan benzersiz sütunlar içerir. Her bir aygıtın birden fazla alt tür olmamasını sağlamak için hem üst hem de alt tablolara bir tür sütunu ekleyebilirsiniz. (ItemID, ItemTypeID) üzerinde çocuklar ve ebeveyn arasında bir FK yapın. FK'leri başka bir yerde istenen bütünlüğü korumak için süper tip veya alt tip tablolar için kullanabilirsiniz. Örneğin, herhangi bir türdeki ItemID'ye izin veriliyorsa, FK'yi üst tabloya oluşturun. Yalnızca SubItemType1'e başvurulabilirse, FK'yi bu tabloya oluşturun. TypeID referans tabloları dışında kalacaktı.

Adlandırma

Adlandırma söz konusu olduğunda, gördüğüm gibi iki seçeneğiniz var (çünkü sadece "ID" nin üçüncü seçimi aklımda güçlü bir anti-desen olduğu için). Üst tablodaki gibi ItemID alt tür anahtarını veya DoohickeyID gibi alt tür adını çağırın. Biraz düşünce ve bu deneyimden sonra, ona DoohickeyID demeyi savunuyorum. Bunun nedeni, alt tür tablo hakkında gerçekten Öğeleri (Doohickeys yerine) gizleyen bir karışıklık olsa da, bu Doohickey tablosuna bir FK oluşturduğunuzda ve sütun adlarının eşleşme!

EAV için veya değil EAV için - Bir EAV veritabanı ile deneyimim

EAV gerçekten yapmanız gereken şeyse, yapmanız gereken budur. Ama ya yapmanız gereken şey olmasaydı?

Bir işte kullanımda olan bir EAV veritabanı oluşturdum. Tanrıya şükür, veri kümesi küçüktür (düzinelerce öğe türü olmasına rağmen) performans kötü değildir. Ancak, veritabanında birkaç binden fazla öğe olması kötü olurdu! Ayrıca, tabloları sorgulamak çok zor. Bu deneyim beni gelecekte mümkünse EAV veritabanlarından uzak durma arzusuna yöneltti.

Şimdi, veritabanımda var olan her alt tip için otomatik olarak PIVOTed görünümleri oluşturan bir saklı yordam oluşturdum. Ben sadece AutoDoohickey sorgulayabilirsiniz. Alt türlerle ilgili meta verilerim, görünüm adlarında kullanılmaya uygun, nesne için güvenli bir ad içeren bir "KısaAd" sütununa sahip. Hatta görünümlerin güncellenebilir hale getirdim! Ne yazık ki, bunları bir birleştirmede güncelleyemezsiniz, ancak onlara mevcut bir satırı ekleyebilirsiniz; bu satır, bir GÜNCELLEME'ye dönüştürülür. Ne yazık ki, yalnızca birkaç sütunu güncelleyemezsiniz, çünkü VIEW'a INSERT-UPDATE dönüştürme işlemi ile hangi sütunları güncellemek istediğinizi belirtmenin bir yolu yoktur: NULL değeri "bu sütunu NULL olarak güncelle" gibi görünüyor "Bu sütunu hiç güncelleme" seçeneğini belirtmek istediniz.

EAV veritabanının kullanımını kolaylaştırmak için tüm bu dekorasyona rağmen, YAVAŞ olduğu için hala bu görünümleri çoğu normal sorgulamada kullanmıyorum. Sorgu koşulları, Valuetabloya kadar geriye doğru itilmiş değildir , bu nedenle filtrelemeden önce bu görünüm türündeki tüm öğelerin ara sonuç kümesini oluşturması gerekir. Ahh. Bu yüzden, her biri farklı bir değer elde etmek için dışarı çıkacak çok, çok birleştirmelerle birçok sorgularım var. Onlar nispeten iyi performans, ama ah! İşte bir örnek. Bunu yaratan SP (ve güncelleme tetikleyicisi) dev bir canavar ve bundan gurur duyuyorum, ancak korumak istediğiniz herhangi bir şey değil.

CREATE VIEW [dbo].[AutoModule]
AS
--This view is automatically generated by the stored procedure AutoViewCreate
SELECT
   ElementID,
   ElementTypeID,
   Convert(nvarchar(160), [3]) [FullName],
   Convert(nvarchar(1024), [435]) [Descr],
   Convert(nvarchar(255), [439]) [Comment],
   Convert(bit, [438]) [MissionCritical],
   Convert(int, [464]) [SupportGroup],
   Convert(int, [461]) [SupportHours],
   Convert(nvarchar(40), [4]) [Ver],
   Convert(bit, [28744]) [UsesJava],
   Convert(nvarchar(256), [28745]) [JavaVersions],
   Convert(bit, [28746]) [UsesIE],
   Convert(nvarchar(256), [28747]) [IEVersions],
   Convert(bit, [28748]) [UsesAcrobat],
   Convert(nvarchar(256), [28749]) [AcrobatVersions],
   Convert(bit, [28794]) [UsesDotNet],
   Convert(nvarchar(256), [28795]) [DotNetVersions],
   Convert(bit, [512]) [WebApplication],
   Convert(nvarchar(10), [433]) [IFAbbrev],
   Convert(int, [437]) [DataID],
   Convert(nvarchar(1000), [463]) [Notes],
   Convert(nvarchar(512), [523]) [DataDescription],
   Convert(nvarchar(256), [27991]) [SpecialNote],
   Convert(bit, [28932]) [Inactive],
   Convert(int, [29992]) [PatchTestedBy]
FROM (
   SELECT
      E.ElementID + 0 ElementID,
      E.ElementTypeID,
      V.AttrID,
      V.Value
   FROM
      dbo.Element E
      LEFT JOIN dbo.Value V ON E.ElementID = V.ElementID
   WHERE
      EXISTS (
         SELECT *
         FROM dbo.LayoutUsage L
         WHERE
            E.ElementTypeID = L.ElementTypeID
            AND L.AttrLayoutID = 7
      )
) X
PIVOT (
   Max(Value)
   FOR AttrID IN ([3], [435], [439], [438], [464], [461], [4], [28744], [28745], [28746], [28747], [28748], [28749], [28794], [28795], [512], [433], [437], [463], [523], [27991], [28932], [29992])
) P;

Aralarında birden çok yolu olabilen öğeler arasındaki ilişkileri bulmaya yardımcı olmak için özel meta verilerden başka bir saklı yordam tarafından oluşturulan başka bir otomatik olarak oluşturulan görünüm türü (Özellikle: Modül-> Sunucu, Modül-> Küme-> Sunucu, Modül-> DBMS- > Server, Module-> DBMS-> Cluster-> Server) ile ilişkili olan kısmını dışarı aktarmak suretiyle yedek oluşturmanız gerekir:

CREATE VIEW [dbo].[Link_Module_Server]
AS
-- This view is automatically generated by the stored procedure LinkViewCreate
SELECT
   ModuleID = A.ElementID,
   ServerID = B.ElementID
FROM
   Element A
   INNER JOIN Element B
      ON EXISTS (
         SELECT *
         FROM
            dbo.Element R1
         WHERE
            A.ElementID = R1.ElementID1
            AND B.ElementID = R1.ElementID2
            AND R1.ElementTypeID = 38
      ) OR EXISTS (
         SELECT *
         FROM
            dbo.Element R1
            INNER JOIN dbo.Element R2 ON R1.ElementID2 = R2.ElementID1
         WHERE
            A.ElementID = R1.ElementID1
            AND R1.ElementTypeID = 40
            AND B.ElementID = R2.ElementID2
            AND R2.ElementTypeID = 38
      ) OR EXISTS (
         SELECT *
         FROM
            dbo.Element R1
            INNER JOIN dbo.Element R2 ON R1.ElementID2 = R2.ElementID1
         WHERE
            A.ElementID = R1.ElementID1
            AND R1.ElementTypeID = 38
            AND B.ElementID = R2.ElementID2
            AND R2.ElementTypeID = 3122
      ) OR EXISTS (
         SELECT *
         FROM
            dbo.Element R1
            INNER JOIN dbo.Element R2 ON R1.ElementID2 = R2.ElementID1
            INNER JOIN dbo.Element C2 ON R2.ElementID2 = C2.ElementID
            INNER JOIN dbo.Element R3 ON R2.ElementID2 = R3.ElementID1
         WHERE
            A.ElementID = R1.ElementID1
            AND R1.ElementTypeID = 40
            AND C2.ElementTypeID = 3080
            AND R2.ElementTypeID = 38
            AND B.ElementID = R3.ElementID2
            AND R3.ElementTypeID = 3122
      )
WHERE
   A.ElementTypeID = 9
   AND B.ElementTypeID = 17

Hibrit Yaklaşım

Bir EAV veritabanının dinamik özelliklerinden bazılarına sahip olmanız GEREKİRse, meta verileri böyle bir veritabanınız varmış gibi oluşturmayı düşünebilirsiniz, bunun yerine aslında supertype / subtype tasarım modelini kullanabilirsiniz. Evet, yeni tablolar oluşturmanız ve sütun eklemeniz ve kaldırmanız ve değiştirmeniz gerekir. Ancak uygun ön işleme ile (EAV veritabanımın Otomatik görünümlerinde yaptığım gibi) çalışmak için gerçek tablo benzeri nesneler olabilir. Sadece, benimki kadar gnarly olmazlardı ve sorgu optimize edici temel tablolara aşağı itmeyi tahmin edebilir (okuma: onlarla iyi performans gösterebilir). Üst tür tablo ile alt tür tablo arasında yalnızca bir birleştirme olur. Uygulamanız, ne yapması gerektiğini keşfetmek için meta verileri okuyacak şekilde ayarlanmış olabilir (veya bazı durumlarda otomatik olarak oluşturulan görünümleri kullanabilir).

Veya çok düzeyli bir alt tür kümeniz varsa, yalnızca birkaç birleşim vardır. Çok düzeyli derken, bazı alt türler ortak sütunları paylaştığında, ancak hepsini paylaşmadığında, diğer birkaç tablonun bir süper tipi olanlar için bir alt tür tablonuz olabilir. Örneğin, Sunucular, Yönlendiriciler ve Yazıcılar hakkında bilgi saklıyorsanız, "IP Aygıtı" ara alt türü anlamlı olabilir.

Henüz gerçek dünyada denemek için önerdiğim gibi henüz böyle bir hibrit süper tip / alt tip EAV-metatable dekore edilmiş veritabanı yapmadığım konusunda uyarı vereceğim. Ama EAV ile yaşadığım problemler küçük değil ve eğer veritabanınız büyük olacak ve çılgın pahalı dev bir donanım olmadan iyi bir performans istiyorsanız, bir şey yapmak muhtemelen mutlak bir zorunluluktur .

Kanımca, gerçek alt tip tabloların kullanımını / oluşturulmasını / değiştirilmesini otomatikleştirmek için harcanan zaman en iyisi olacaktır. Veri tarafından tahrik esneklik odaklanarak çekici (ve inanın bana bu yüzden EAV ses yapar aşk birisi bir eleman türüne yeni bir özellik için beni sorduğunda ben 18 hakkında saniyeler içinde ekleyebilirsiniz ve hemen web sitesinde veri girme başlayabilirsiniz nasıl ). Ancak esneklik birden fazla şekilde gerçekleştirilebilir! Ön işleme bunu yapmanın başka bir yoludur. Bu kadar güçlü bir yöntemdir ki, tamamen veriye dayalı olmanın avantajlarını ancak sabit kodlu olmanın performansını sağlar.

(Not: Evet, bu görünümler gerçekten bu şekilde biçimlendirilmiştir ve PIVOT olanlar gerçekten güncelleme tetikleyicilerine sahiptir. :) Birisi gerçekten uzun ve karmaşık GÜNCELLEME tetikleyicisinin korkunç acı verici ayrıntılarıyla ilgileniyorsa, bana bildirin ve ben gönderirim sizin için bir örnek.)

Ve Bir Fikir Daha

Tüm verilerinizi tek bir tabloya yerleştirin. Sütunlara genel adlar verin ve birden çok amaç için bunları yeniden kullanın / kötüye kullanın. Onlara mantıklı isimler vermek için bunlara bakışlar oluşturun Uygun veri türü kullanılmayan bir sütun olmadığında sütun ekleyin ve görünümlerinizi güncelleyin. Uzunluğum alt tip / süper tip hakkında olmasına rağmen, bu en iyi yol olabilir.


Her bir alt tip tablosunun ana ve nadir alanlardan PK'ya sahip olduğu bu tasarımı düşündüm. Ben üst ve her alt tür tablo türü alanı koymak ve sonra onlara bir CHECK kısıtlama koymak düşündüm. Bu tasarımdan kaçınmaya karar verdim çünkü yeni bir cihazın izlenmesi gerektiğinde yeni bir tablo ve birçok birebir ilişki gerektiriyordu. Dağınık ve esnek görünmüyordu. Yine de girdilerinizi takdir ediyorum.
TheSecretSquad

Bir işte kullanımda olan bir EAV veritabanı oluşturdum. Tanrıya şükür, veri kümesi küçüktür (düzinelerce öğe türü olmasına rağmen) performans kötü değildir. Ancak, veritabanında birkaç binden fazla öğe varsa olurdu. Bu deneyim beni gelecekte mümkünse EAV veritabanlarından uzak durma arzusuna yöneltti, çünkü sorgulamak çok zor.
ErikE

Ayrıca, gerçek alt tip tabloların kullanımını / oluşturulmasını / değiştirilmesini otomatikleştirmek için harcanan zaman, bence, en iyisi olacaktır.
ErikE

EAV modelini inceledikten sonra, öznitelik değerlerinin bir veri türünü (bu durumda tüm dize) paylaşmaya zorlandığını fark ettim. Ayrıca, EAV kurulumunun sorgulanması bir angarya olacaktır. Süper tip / alt tip daha iyi görünüyor. Şimdi sorum şu, bazı tablolar sadece belirli cihaz türlerine izin veriyor. Bunu her tabloya bir aygıt sınıfı kimliği (telefon, bilgisayar, yönlendirici) yerleştirip bu alana bir denetim kısıtlaması koyarak doğrulayabilir miyim yoksa bu alanı alt tür tablolardan hariç tutabilir miyim ve her birinde bir tetikleyici kullanabilir miyim? Referans için lütfen ERD3'e bakınız .
TheSecretSquad

1
EAV verilerini sorgulamak için, sorgulamak istediğiniz veriler için ilişkisel tabloların datamart'ını oluşturmak ve sonra bunları bir komut dosyası kullanarak doldurmak nadir değildir. Sorgular daha hızlı çalışır, ancak yalnızca datamart'a koyduğunuz verilere karşı çalışır ve kurulum oldukça planlama gerektirir.
FrustratedWithFormsDesigner

6

Sizin durumunuzda en iyi yaklaşım Entity-Attribute-Value (EAV) modelindeki bir değişikliktir. Bazı şekillerde yararsız olduğu ve çoğu zaman yanlış kullandığından EAV'den utanan birçok insan var. Bununla birlikte, EAV, özel gereksinimleriniz için iyi çalışan bir çözümdür.

Durumunuza dahil etmek istediğiniz varyasyon özellikleri varlıklarınızdan bir seviye uzakta (yani envanter öğeleriniz) soyutlamaktır. Esasen , özellik listesi olan cihaz türlerini tanımlamak istersiniz . Ardından , bu tür aygıtların sahip olması gereken özelliklerin her biri için değerlere sahip aygıt örnekleri tanımlarsınız .

İşte bir ERD çizimi:

ERD

DEVICE_ATTRIBUTEher bir genel özellik türü için değerleri içerir. DEVICE_TYPEBelirli bir aygıt türüne uygulanan genel özniteliklerin listesini tanımlar (bunlar TYPICAL_DEVICE_ATTRIBUTEs.

Bu, farklı türdeki cihazların farklı özellik listelerine sahip olmasına izin verirken bir cihaz için hangi özelliklerin doldurulması gerektiğini kontrol etmenizi sağlar. Ayrıca, özniteliklerini birbirine göre sıralayarak cihazlar arasında karşılaştırma yapmanızı da kolaylaştırır.


Bu, ssmusoke'un tavsiye ettiği şeye benziyor. Onun tavsiyesini kullanarak ERD'mi değiştirdim ve sizinkiyle eşleşiyor gibi görünüyor. Http://www.dividegraphics.com/ERD2.jpg adresinden yeni RD'ye göz atabilir ve görüşlerinizi bildirebilirsiniz.
TheSecretSquad

@reallythecrash - Haklısın, ssmusoke ile aynı temel yaklaşımı öneriyorum, hem modelin yapısını hem de EAV'yi kullanma mantığını daha kolay hale getirme umuduyla cevabım için farklı bir yol aldım. birçok insan (haksız yere) bir anti-desen olarak kınıyor.
Joel Brown

Bazı araştırmalardan sonra insanların neden EAV'yi bir anti-model olarak kabul edebileceğini görüyorum. EAV kullanarak veri depolamak basit ama veri türlerini sorgulamak ve korumak için özellikle karmaşık olduğunu düşünüyorum. Bence dar bir amaca sahip bir model ve bunu düzgün bir şekilde uygulayabilen deneyimli geliştiriciler tarafından kullanılmalı, yani ben değil. Muhtemelen supertype / subtype paradigmasını tercih edeceğim.
TheSecretSquad

@JoelBrown - bu diyagramı çizmek için hangi yazılımı kullandınız?
Vidar

@Vidar - Visio'yu, James Martin görsel kurallarını kullanmak için oluşturduğum ve kabataslak özel bir çizgi deseni ile çizdiğim ERD smartshapes ile kullandım. Bunun hızlı / taslak veri modelleri için kullanmak için iyi bir araç olduğunu düşünüyorum. Diyagram çok resmi olduğunda, bazı insanların bittiğini düşünmelerine yol açabilir, bu yüzden kabataslak bir şey insanların bir veri modelinin ne kadar sağlam / bitmiş olduğu ile ilgili sonuçlara atlamasını önlemeye yardımcı olur.
Joel Brown

1
  1. Genel yaklaşım aşağıdaki gibidir:

a) Farklı aygıtların özniteliklerini bir aygıt türüyle ele almak için bir Varlık Öznitelik Değeri modeli yaklaşımı. Her cihaz türünde, değerlerini izlediğiniz özelliklerin bir listesi bulunur

b) Her aygıt türü için, envanter ayrıntılarını tek bir aygıta karşılık gelen seri numarasına göre izlersiniz.

  1. Böylece aşağıdaki tablolarla sonuçlanırsınız:

a) Nitelikler - tüm cihazların niteliklerini tanımlayın (her şey bu tabloya girer) sütunlar: kimlik, ad, açıklama

b) Öğe Nitelikleri - belirli bir cihaz için izin verilen nitelikleri tanımlar - itemid, attributeid

c) Öğe Tanımı - Black Berry Torch 4500, Iphone 4S, Iphone 3S vs - id, isim, açıklama, categoryid (cep telefonları, anahtarlar vb. gibi kategoriler eklemek istiyorsanız)

d) Cihazlar - tek tek cihazlar - id, itemid, envanter tarihi, devre dışı bırakma tarihi, seri numarası ... (temel olarak bir cihaz için diğer tüm özellikler)

Aygıt işlemleriyle ilgili başka bilgileri izlemek istiyorsanız, aygıta bağlı olarak daha fazla tablo ekleyebilirsiniz.


Girişiniz için teşekkürler. Bu benim aradığım şeyle aynı, nasıl yapılacağını anlayamadım. ERD'mi özelliklerinizi yansıtacak şekilde değiştirdim. Her cihaz türü için izin verilen tüm özellikleri girmek için daha fazla çalışma gerektiriyor gibi görünüyor, ancak aynı zamanda maksimum esneklik sunduğu anlaşılıyor. İstediğim gibi çalışıp çalışmadığını görmek için küçük bir prototip yapacağım. Tekrar teşekkürler. Eğer bir göz atmak ve doğru yolda olup olmadığımı bildirmek isterseniz, değişiklikleri içeren bir ERD yükledim. http://www.dividegraphics.com/ERD2.jpg
TheSecretSquad

Evet, doğru yoldasınız.
Stephen Senkomago Musoke

EAV çok fazla esneklik sunacak, ancak aynı zamanda çalışmasını sağlamak için çok daha fazla meta veriye sahipsiniz.
FrustratedWithFormsDesigner

Sistem depolar öğeleri, telefonlar, geniş bir yelpazede geçer zaman @FrustratedWithFormsDesigner vb adet, dizüstü bilgisayarlar, kaçınılmaz görünüyor ... söyleyebilirim fazla tabloları daha meta iyi
Stephen Senkomago Musoke

1
@ssmusoke: Kabul etti, ama bu noktayı vurgulamak istedim çünkü insanların meta verilerin önemini fark etmediklerini gördüm ve daha sonra EAV uygulamaları bir kabus oldu.
FrustratedWithFormsDesigner
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.