Arkadaşlık veritabanı yapısı tasarlama: Çok değerli bir sütun kullanmalı mıyım?


9

Diyelim ki User_FriendListşu özelliklere sahip bir tablonuz var :

CREATE TABLE User_FriendList (
    ID ...,
    User_ID...,
    FriendList_IDs...,
    CONSTRAINT User_Friendlist_PK PRIMARY KEY (ID)
);

Diyelim ki söz konusu tablonun aşağıdaki verileri içerdiğini varsayalım:

 + ---- + --------- + --------------------------- +
 | ID | Kullanıcı_kimliği | Arkadaş listesi_kimliği             |
 + ---- + --------- + --------------------------- +
 | 1 | 102 | 2: 15: 66: 35: 26: 17: |
 + ---- + --------- + --------------------------- +
 | 2 | 114 | 1: 12: 63: 33: 24: 16: 102 |
 + ---- + --------- + --------------------------- +
 | 3 | 117 | 6: 24: 52: 61: 23: 90: 97: 118 |
 + ---- + --------- + --------------------------- +

Not: “:” işareti olduğunda (kolon) ayraç patlayan bir içine PHP array.

Sorular

Yani:

  • Bu “store” için uygun bir yolu mu IDsa FriendList?

  • Ya da, bunun yerine, FriendIdher birinde tek bir değere sahip tek tek satırlar olmalı ve belirli bir listenin tüm satırlarını almam gerektiğinde , sadece bir sorgu yapmalı mıyım SELECT * FROM UserFriendList WHERE UserId = 1?


3
Bunu okumanızı tavsiye ederim: stackoverflow.com/questions/3653462/…
tombom

Onlarla hiçbir şey yapmayı planlamadığınız ve özellikle veri kalitesini önemsemediğiniz sürece, kimlikleri depolamanın biraz uygun bir yoludur.
mustaccio

Bence codedodle.com/2014/12/social-network-friends-database.html en iyi çözümlerden biri olabilir.
Gupta

Yanıtlar:


19

Tek bir bilgiyi yönetme

İşletme alan adınızda,

  • bir Kullanıcının sıfır-bir-veya-çok Arkadaşı olabilir ;
  • bir Arkadaş önce Kullanıcı olarak kaydedilmelidir ; ve
  • bir Arkadaş Listesinin tek değerlerini arayacak ve / veya ekleyecek ve / veya kaldıracak ve / veya değiştireceksiniz ;

Daha sonra , her bir araya belirli bir veri Friendlist_IDsbirden çok sütun temsil bilgi ayrı bir parça çok kesin bir anlam taşımaktadır. Bu nedenle, bahsedilen sütun

  • uygun bir grup açık kısıtlama gerektirir ve
  • değerleri, birkaç ilişkisel işlem (veya bunların kombinasyonları) vasıtasıyla bireysel olarak manipüle edilme potansiyeline sahiptir.

Kısa cevap

Sonuç olarak, Friendlist_IDs(a) 'da yer alan değerlerin her birini, (b) Kullanıcılar arasında gerçekleşebilecek kavramsal düzey ilişkilendirme türünü temsil eden bir tablodaki satır başına yalnızca tek bir değeri kabul eden bir sütun , yani bir Dostluk - Aşağıdaki bölümlerde örnek vereceğim -.

Bu yolla, (i) söz konusu tabloyu matematiksel bir ilişki olarak ve (ii) söz konusu sütunu , tabii ki MySQL ve SQL lehçe izni kadar - bir matematiksel ilişki özelliği olarak ele alabileceksiniz.

Neden?

Çünkü verilerin ilişkisel model tarafından oluşturulur, E. F. Codd , talep sahip sütunlar oluşmaktadır tabloları sahip olan tam bir geçerli değerini alan veya tip sıra başına; bu nedenle, (1) 'de söz konusu alan veya tipin birden fazla değerini içerebilen bir sütuna sahip bir tablonun bildirilmesi, matematiksel bir ilişkiyi temsil etmez ve (2), yukarıda belirtilen teorik çerçevede önerilen avantajların elde edilmesine izin vermez.

Kullanıcılar Arasındaki Dostlukların Modellenmesi : Önce iş ortamı kurallarının tanımlanması

Diğer faktörlerin yanı sıra, ilginin farklı yönleri arasında var olan ilişki türlerini tanımlaması gereken ilgili iş kurallarının tanımlanması nedeniyle - her şeyden önce - ilgili kavramsal şemayı sınırlayan bir veritabanı şekillendirmeye başlamanızı şiddetle tavsiye ederim . , uygulanabilir varlık türleri ve özellikleri ; Örneğin:

  • Bir Kullanıcı öncelikle kendi Kullanıcı Kimliği ile tanımlanır
  • Bir Kullanıcı dönüşümlü olarak FirstName , LastName , Cinsiyet ve Doğum Tarihi birleşimi ile tanımlanır.
  • Bir Kullanıcı dönüşümlü kendi tanımlanır adı
  • Bir kullanıcı bir istek sahibi sıfır-bir-veya-birçok arkadaşlıklar
  • Bir kullanıcı olan Adresler, sıfır-bir-veya-birçok arkadaşlıklar
  • Bir Dostluk öncelikle RequesterId ve AddresseeId kombinasyonu ile tanımlanır.

Açıklayıcı IDEF1X diyagramı

Bu şekilde, daha önce formüle edilen kuralların çoğunu birleştiren, Şekil 1'de gösterilen IDEF1X 1 diyagramını türetebildim :

Şekil 1. Kullanıcı Dostlukları IDEF1X Şeması

Gösterildiği üzere, Talep Eden ve Adresler, ekspres gösterimlerin olan Roller belirli tarafından yürütülen Kullanıcılar belirli bir yer almak Dostluk .

Öyleyse, Dostluk varlık türü , aynı varlık türünün, yani Kullanıcı'nın farklı yinelemelerini içerebilecek çok-çok (M: N) kardinalite oranının bir ilişkilendirme türünü tasvir eder . Bu nedenle, “Malzeme Listesi” veya “Parça Patlaması” olarak bilinen klasik yapıya bir örnektir.


1 Bilgi Modellemesi için Entegrasyon Tanımı ( IDEF1X ),Aralık 1993'te ABD Ulusal Standartlar ve Teknoloji Enstitüsü (NIST)tarafından standart olarak oluşturulmuş, oldukça tavsiye edilebilir bir tekniktir. Kesin olarak (a)ilişkisel modelin tek yaratıcısı olan Dr. EF Codd tarafından yazılan erken teorik materyal; (b) Dr. PP Chen tarafından geliştirilen verilerin varlık-ilişki görünümü; ve ayrıca (c) Robert G. Brown tarafından oluşturulan Mantıksal Veritabanı Tasarım Tekniği.


Açıklayıcı SQL-DDL mantıksal tasarımı

Daha sonra, yukarıda sunulan IDEF1X diyagramından, aşağıdakine benzer bir DDL düzenlemesi bildirmek çok daha “doğal” olur:

-- You should determine which are the most fitting 
-- data types and sizes for all the table columns 
-- depending on your business context characteristics.

-- At the physical level, you should make accurate tests 
-- to define the mostconvenient INDEX strategies based on 
-- the pertinent query tendencies.

-- As one would expect, you are free to make use of 
-- your preferred (or required) naming conventions. 

CREATE TABLE UserProfile ( -- Represents an independent entity type.
    UserId          INT      NOT NULL,
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    BirthDate       DATE     NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    Username        CHAR(20) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT UserProfile_PK  PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- Single-column ALTERNATE KEY.
);

CREATE TABLE Friendship ( -- Stands for an associative entity type.
    RequesterId     INT      NOT NULL,
    AddresseeId     INT      NOT NULL, -- Fixed with a well-delimited data type.
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Friendship_PK            PRIMARY KEY (RequesterId, AddresseeId), -- Composite PRIMARY KEY.
    CONSTRAINT FriendshipToRequester_FK FOREIGN KEY (RequesterId)
        REFERENCES UserProfile (UserId),
    CONSTRAINT FriendshipToAddressee_FK FOREIGN KEY (AddresseeId)
        REFERENCES UserProfile (UserId)
);

Bu moda da:

  • her temel tablo ayrı bir varlık türünü temsil eder;
  • her sütun , ilgili varlık türünün tek bir özelliğini temsil eder ;
  • içerdiği tüm değerlerin , INT, DATETIME, CHAR, vb.Gibi belirli ve iyi tanımlanmış bir kümeye ait olduğunu garanti etmek için her sütun için belirli bir veri türü a sabitlenir ; ve
  • tüm tablolarda tutulan satırlar biçimindeki iddiaların kavramsal şemada belirlenen iş kurallarını karşıladığından emin olmak için birden fazla kısıtlama b yapılandırılır (bildirimsel olarak) .

Tek değerli bir sütunun avantajları

Gösterildiği gibi şunları yapabilirsiniz:

  • Sütun için veritabanı yönetim sistemi (kısalık için DBMS) tarafından uygulanan referans bütünlüğünden yararlanın Friendship.AddresseeId, çünkü sütuna referans yapan bir DIŞ ANAHTAR (kısalık için FK) olarak sınırlamak UserProfile.UserId, her değerin mevcut bir satıra işaret ettiğini garanti eder .

  • Bir oluşturma kompozit kolonların kombinasyonundan oluşan birincil anahtar (PK) (Friendship.RequesterId, Friendship.AddresseeId)zarif tüm INSERTed satırları ayırt ve doğal olarak onların korunmasına yardımcı olur benzersizliğini .

    Tabii ki, bu , sistem tarafından atanan vekil değerler (örneğin, Microsoft SQL Server'daki IDENTITY özelliğiyle veya MySQL'deki AUTO_INCREMENT özniteliğiyle ayarlanan ) ve yardımcı INDEX için fazladan bir sütunun eklenmesinin tamamen gereksiz olduğu anlamına gelir .

  • Tutulan değerleri , DBMS'nin ilgili otomatik doğrulamaya dikkat etmesine izin vererek, Friendship.AddresseeIdkesin bir veri türü c ile sınırlandırın (örneğin, UserProfile.UserIdbu durumda INT için oluşturulmuş olanla eşleşmelidir ) .

    Bu faktör ayrıca (a) karşılık gelen yerleşik tip fonksiyonlarının kullanılmasına ve (b) disk alanı kullanımını optimize etmeye yardımcı olabilir .

  • Sütun için küçük ve hızlı alt INDEX'leri yapılandırarak fiziksel düzeyde veri alımını optimize edin , çünkü bu fiziksel öğeler söz konusu sütunu içeren sorguları hızlandırmaya önemli ölçüde yardımcı olabilir .Friendship.AddresseeId

    Elbette, sen örneğin bir tek sütunlu INDEX koyabilirsiniz Friendship.AddresseeId, tek başına bir çok sütunlu bir o kapsar Friendship.RequesterIdve Friendship.AddresseeIdveya her ikisi.

  • Aynı sütun içinde toplanan farklı değerleri (büyük olasılıkla çoğaltılmış, yanlış yazılmış, vb.) “Arayarak” ortaya çıkan gereksiz karmaşıklıktan kaçının, sisteminizin işleyişini yavaşlatacak bir eylem biçimi, söz konusu görevi yerine getirmek için kaynak ve zaman alıcı ilişkisel olmayan yöntemlere başvurmak zorundadır.

Bu nedenle, her bir tablo sütununun d türünü doğrulukla işaretlemek için ilgili iş ortamını dikkatle analiz etmenin çeşitli nedenleri vardır .

Açıklandığı gibi, veritabanı tasarımcısı tarafından oynanan rol, (1) ilişkisel model tarafından sunulan mantıksal düzey faydaları ve (2) seçilen DBMS tarafından sağlanan fiziksel mekanizmaları en iyi şekilde kullanmak için çok önemlidir .


a , b , c , d Açıkça,DOMAIN oluşturmayı (ayırt edici bir ilişkisel özellik)destekleyenSQL platformlarıyla (örn. Firebird ve PostgreSQL )çalışırken, yalnızca ilgili (uygun şekilde kısıtlanmış ve bazen) değerleri kabul eden sütunlar bildirebilirsiniz. DOMAIN).


Söz konusu veritabanını paylaşan bir veya daha fazla uygulama programı

Eğer istihdam zorunda olduklarında arraysuygulama programı (ler) veritabanı girişini kodunda, sadece ilgili veri setini (lar) almak gerekir tam olarak ve ardından “Bağlanma” it (onları) ilişkin kod yapısına veya yürütmek gerçekleşmesi gereken ilişkili uygulama (lar) işlemi.

Tek değerli sütunların diğer avantajları: Veritabanı yapısı uzantıları çok daha kolaydır

AddresseeIdVeri noktasını ayrılmış ve düzgün bir şekilde yazılan sütununda tutmanın bir başka avantajı, aşağıda örnekleyeceğim gibi veritabanı yapısının genişletilmesini önemli ölçüde kolaylaştırmasıdır.

Senaryo ilerlemesi: Arkadaşlık Durumu kavramını dahil etme

Yana Arkadaşlıklar zaman içinde gelişmeye edebilir böylece sen olurdu, böyle bir fenomenin izlemek gerekebilir, (i) kavramsal şemayı genişletmek ve (ii) mantıksal düzende birkaç tablo beyan ederim. Şimdi, yeni anonim şirketleri tanımlamak için bir sonraki iş kurallarını ayarlayalım:

  • Bir Arkadaşlık birden çok Arkadaşlığa sahiptir
  • Bir FriendshipStatus , öncelikle RequesterId , AddresseeId ve SpecifiedDateTime öğelerinin birleşimi ile tanımlanır.
  • Bir Kullanıcı sıfır bir veya birden fazla FriendshipStatuses belirtir
  • Bir Durum, sıfır bir veya birçok FriendshipStatuses'u sınıflandırır
  • Bir Durum öncelikle StatusCode tarafından tanımlanır
  • Bir Durum dönüşümlü olarak tanımlanır Adı

Genişletilmiş IDEF1X diyagramı

Art arda, önceki IDEF1X diyagramı, yukarıda açıklanan yeni varlık türlerini ve ilişki türlerini içerecek şekilde genişletilebilir. Yenileriyle ilişkili önceki unsurları gösteren bir diyagram Şekil 2'de sunulmaktadır :

Şekil 2. Dostluk Durumu IDEF1X Şeması

Mantıksal yapı eklemeleri

Daha sonra DDL düzenini aşağıdaki beyanlarla uzatabiliriz:

--
CREATE TABLE MyStatus ( -- Denotes an independent entity type.
    StatusCode CHAR(1)  NOT NULL,
    Name       CHAR(30) NOT NULL,
    --
    CONSTRAINT MyStatus_PK PRIMARY KEY (StatusCode),
    CONSTRAINT MyStatus_AK UNIQUE      (Name) -- ALTERNATE KEY.
); 

CREATE TABLE FriendshipStatus ( -- Represents an associative entity type.
    RequesterId       INT      NOT NULL,
    AddresseeId       INT      NOT NULL,
    SpecifiedDateTime DATETIME NOT NULL,
    StatusCode        CHAR(1)  NOT NULL,
    SpecifierId       INT      NOT NULL,
    --
    CONSTRAINT FriendshipStatus_PK             PRIMARY KEY (RequesterId, AddresseeId, SpecifiedDateTime), -- Composite PRIMARY KEY.
    CONSTRAINT FriendshipStatusToFriendship_FK FOREIGN KEY (RequesterId, AddresseeId)
        REFERENCES Friendship  (RequesterId, AddresseeId), -- Composite FOREIGN KEY.
    CONSTRAINT FriendshipStatusToMyStatus_FK   FOREIGN KEY (StatusCode)
        REFERENCES MyStatus    (StatusCode),
    CONSTRAINT FriendshipStatusToSpecifier_FK  FOREIGN KEY (SpecifierId)
        REFERENCES UserProfile (UserId)      
);

Sonuç olarak, belirli bir Arkadaşlığın Durumunun her güncel hale getirilmesi gerektiğinde, Kullanıcılar yalnızca aşağıdakileri içeren yeni bir satır EKLEMEKTEDİR:FriendshipStatus

  • ilgili satırdan alınan uygun RequesterIdve AddresseeIddeğerler Friendship;

  • yeni ve anlamlı StatusCodedeğer - içinden alınmış MyStatus.StatusCode-;

  • tam INSERTion anı, yani - özellikle SpecifiedDateTimebir sunucu fonksiyonunun kullanılması , böylece onu güvenilir bir şekilde alabilmeniz ve muhafaza edebilmeniz için; ve

  • SpecifierIdİlgili işaret eder değeri UserIdyeni girilen FriendshipStatus(ler) tesisleri-uygulamanızın yardımıyla, -ideally sisteme.

Bu kapsamda, MyStatustablonun (a) son kullanıcı olan PK değerleri ile, uygulama programcısı ve DBA dostu olan ve (b) fiziksel uygulama düzeyindeki baytlar açısından küçük ve hızlı olan aşağıdaki verileri içerdiğini varsayalım. -:

 + ------------ + ----------- +
 | DurumKodu | İsim       |
 + ------------ + ----------- +
 | R | İstendi |
 + ------------ + ----------- +
 | A | Kabul edildi |
 + ------------ + ----------- +
 | D | Reddedildi |
 + ------------ + ----------- +
 | B | Bloqued |
 + ------------ + ----------- +

Bu nedenle, FriendshipStatustablo aşağıda gösterildiği gibi verileri tutabilir:

 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | Gereksinim | Adres | BelirtilenTarihZamanı        | DurumKodu | SpecifierId |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-01 16: 58: 12.000 | R | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-02 09: 12: 05.000 | A | 1748 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-04 10: 57: 01.000 | B | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-07 07: 33: 08.000 | R | 1748 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +
 | 1750 | 1748 | 2016-04-08 12: 12: 09.000 | A | 1750 |
 + ------------- + ------------- + --------------------- ---- + ------------ + ------------- +

Gördüğünüz gibi, FriendshipStatustablonun bir zaman serisi içermesi amacına hizmet ettiği söylenebilir .


Alakalı yayınlar

Ayrıca ilginizi çekebilir:

  • Bu cevap , iki farklı varlık türü arasında ortak bir çoktan çoğa ilişki ile başa çıkmak için temel bir yöntem öneriyorum.
  • Bu diğer yanıtı gösteren, Şekil 1'de gösterilen IDEF1X diyagramı . “ Evlilik ve Progeny” adlı varlık türlerine özellikle dikkat edin , çünkü bunlar “Parça Patlama Sorunu” nun nasıl ele alınacağına dair iki örnektir.
  • Farklı bilgilerin tek bir sütunda tutulması hakkında kısa bir tartışma sunan bu yazı .
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.