मुझे दोस्ती के लिए एक संबंध तालिका कैसे डिजाइन करनी चाहिए?


33

यदि Aएक दोस्त है B, तो क्या मुझे दोनों मूल्यों को संग्रहीत करना चाहिए ABऔर BA, या एक पर्याप्त है? दोनों तरीकों के फायदे और नुकसान क्या हैं।

यहाँ मेरा अवलोकन है:

  • अगर मैं दोनों रखता हूं तो मुझे एक दोस्त से अनुरोध प्राप्त होने पर दोनों को अपडेट करना होगा।
  • यदि मैं दोनों को नहीं रखता, तो मुझे JOINइस तालिका के साथ कई करने में कठिनाई हुई ।

वर्तमान में, मैं रिश्ते को एक तरह से रखता हूं।

यहाँ छवि विवरण दर्ज करें

तो मुझे इस मामले में क्या करना चाहिए? कोई सुझाव?


क्या आप एक मंच के लिए प्रतिबद्ध हैं, या यह एक सैद्धांतिक सवाल है?
निक चम्मास

हाइब्रिड एप्रोच के बारे में: अलग-अलग टेबलों में क्रमशः आवश्यक और बिना मैत्री वाले मॉडल के लिए, सुनिश्चित करें कि दोस्ती उन टेबल में से एक में डाली गई है, जो आज के एसक्यूएल उत्पादों का उपयोग करने के लिए अच्छा नहीं है :(
onedaywhen

@onedaywhen - हाँ, एक ग्राफ़ डेटाबेस के लिए अधिक उपयुक्त लगता है ।
निक चम्मास

@NickChammas: यह सैद्धांतिक सवाल नहीं है। मैं उस पर काम कर रहा हूं mysqlजो अमेज़ॅन क्लाउड में संग्रहीत है।
चैन

1
@Chan - आह इसका मतलब है कि आप रिश्ते को लागू करने के लिए चेक बाधाओं का उपयोग नहीं कर सकते हैं केवल एक तरह से संग्रहीत किया जाता है (MySQL इन लागू नहीं करता है)
मार्टिन स्मिथ

जवाबों:


30

मैं एबी और बीए को स्टोर करूंगा। एक मित्रता वास्तव में एक दो-तरफ़ा संबंध है, प्रत्येक इकाई दूसरे से जुड़ी हुई है। भले ही सहज रूप से हम "दोस्ती" को दो लोगों के बीच एक लिंक के रूप में सोचते हैं, एक संबंधपरक दृष्टिकोण से यह अधिक है जैसे "ए का एक दोस्त बी" और "बी का एक दोस्त ए" है। दो रिश्ते, दो रिकॉर्ड।


3
बहुत धन्यवाद। मुझे वास्तव में आपके विचार के बारे में सावधानी से सोचने की आवश्यकता है! कारण यह है कि मैं एबी और बीए को संग्रहीत करने से बचता हूं क्योंकि भंडारण के बाद से, जब भी मेरी दोस्ती होती है, मेरी मेज दो बार अधिक से अधिक स्टोर होती है।
चैन

1
आप भंडारण के बारे में सही हैं, लेकिन याद रखें कि यदि पूर्णांकों के रूप में संग्रहीत किया जाता है, तो प्रत्येक मित्र-मित्र संबंध लगभग 30 बायस (2 रिकॉर्ड x 3 कॉलम x 4 बाइट्स प्रति पूर्णांक = 24 बाइट्स प्लस कुछ पैडिंग) होगा। 10 दोस्तों के साथ 1 मिलियन लोग अभी भी केवल 300MB डेटा के आसपास होंगे।
डेटागोड

1
डेटागोड: यह सही है!
चैन

इस तरह से मैंने अपनी सारणी को एबी और बीए के रूप में भी डिजाइन किया।
kabuto178

2
साथ ही, ऐसी स्थितियों में जहां केवल एबी और बीए नहीं है, यह 'लंबित मित्र अनुरोध' का प्रतिनिधित्व कर सकता है।
ग्रेग

13

दोस्ती सममित करने का इरादा है, तो (यानी यह संभव के लिए नहीं है A दोस्तों के साथ होने के लिए Bतो मैं सिर्फ यह सुनिश्चित करना कि प्रत्येक रिश्ता सिर्फ एक ही रास्ता दर्शाया जा सकता है एक चेक बाधा के साथ एक तरह से संबंध की दुकान थी, लेकिन नहीं इसके विपरीत)।

इसके अलावा मैं सरोगेट आईडी को खोदूंगा और इसके बजाय एक समग्र पीके (और संभवतः एक उल्टा स्तंभ पर एक समग्र अद्वितीय सूचकांक) भी होगा।

CREATE TABLE Friends
  (
     UserID1 INT NOT NULL REFERENCES Users(UserID),
     UserID2 INT NOT NULL REFERENCES Users(UserID),
     CONSTRAINT CheckOneWay CHECK (UserID1 < UserID2),
     CONSTRAINT PK_Friends_UserID1_UserID2 PRIMARY KEY (UserID1, UserID2),
     CONSTRAINT UQ_Friends_UserID2_UserID1 UNIQUE (UserID2, UserID1)
  ) 

आप उन प्रश्नों को नहीं कहते हैं जो इसे कठिन बनाते हैं लेकिन आप हमेशा एक दृश्य बना सकते हैं

CREATE VIEW Foo
AS
SELECT UserID1,UserID2 
FROM Friends
UNION ALL
SELECT UserID2,UserID1 
FROM Friends

मुझे पता है कि यह काफी पुराना है, इसलिए इसे खोदने के लिए खेद है। यह बेहतर नहीं होगा करने के लिए नहीं परिभाषित रिवर्स दोस्ती सूचकांक UNIQUEपर नहीं डाल अनावश्यक और निरर्थक अतिरिक्त बोझ के क्रम में INSERTरों? चूंकि हमारे पास PRIMARY KEY (a,b)और चूंकि पीके है UNIQUE, इसलिए उलट KEY (b,a)भी UNIQUEकोई बात नहीं है।
tfrommen

1
@tf अनुमान है कि quer that अनुकूलक पर निर्भर करता है। जैसा कि आप इंगित करते हैं कि केवल एक ही तरीके की जांच करना आवश्यक है ताकि सम्मिलित योजना वैसे भी ऐसा कर सके। प्रश्न MySQL को टैग किया गया है - यह पता नहीं है कि यह कैसे व्यवहार करता है।
मार्टिन स्मिथ

मुझे पता है कि यह एक पुराना उत्तर है, लेकिन मैं सिर्फ इस पर ठोकर खाने वाले किसी व्यक्ति को इंगित करना चाहता हूं कि MySQL पूरी तरह से CHECK बाधाओं की अनदेखी करता है (हालांकि यह उन्हें सफलतापूर्वक "पार्स" करेगा) इसलिए यह दृष्टिकोण संभवतः इस तकनीक के साथ जाने का तरीका नहीं है।
मीका

@ मायका सच। मुझे यह पता नहीं था कि 2012 में। फिर भी अन्य DBMS में काम करेगा ...
मार्टिन स्मिथ

उस के लिए एक दृश्य लागू करने के लिए +1। AB & BA संग्रहीत होने से असंगतता आती है (यदि संबंध द्वि-दिशात्मक नहीं है), जबकि यह तरीका एक बेहतर तरीका है
imans77

7

एक "दोस्ती" को हमेशा दो-तरफा / पारस्परिक माना जाता है, मैं शायद इसे कुछ इस तरह से संभालूंगा।

CREATE TABLE person (
    person_id int IDENTITY(1,1) PRIMARY KEY,
    ...other columns...
)

CREATE TABLE friendship (
    friendship_id int IDENTITY(1,1) PRIMARY KEY,
    ...other columns, if any...
)

CREATE TABLE person_friendship (
    person_id int NOT NULL,
    friendship_id int NOT NULL
    PRIMARY KEY (person_id, friendship_id)
)

इसका परिणाम यह होता है कि आप इसे "व्यक्ति" से "व्यक्ति" में शामिल करते हैं, "व्यक्ति" से "दोस्ती" के लिए कई-से-कई जुड़ जाते हैं। यह जुड़ाव और बाधाओं को सरल करेगा, लेकिन एक ही "दोस्ती" में दो से अधिक लोगों को अनुमति देने का दुष्प्रभाव है (हालांकि शायद अतिरिक्त लचीलापन एक संभावित लाभ होगा)।


यह मूल रूप से एक समूह / सदस्यता पैटर्न है। दिलचस्प विचार, हालांकि।
einSelbst

4

आपको पंक्तियों की संख्या को दोगुना करने के बजाय दोस्ती के आसपास अनुक्रमित को परिभाषित करने की आवश्यकता हो सकती है:

CREATE TABLE person
(
    person_id INT NOT NULL AUTO_INCREMENT,
    ...
    PRIMARY KEY (person_id)
);
CREATE TABLE friendship
(
    friend_of INT NOT NULL,
    friend_to INT NOT NULL,
    PRIMARY KEY (friend_of,friend_to),
    UNIQUE KEY friend_to (friend_to,friend_of)
);

इस तरह, आप अनुक्रमित के लिए भंडारण को दोगुना करते हैं, लेकिन तालिका डेटा के लिए नहीं। नतीजतन, यह डिस्कस्पेस पर 25% की बचत होनी चाहिए। MySQL क्वेरी ऑप्टिमाइज़र केवल अनुक्रमणिका श्रेणी स्कैन का चयन करेगा, यही कारण है कि अनुक्रमणिका को कवर करने की अवधारणा यहाँ अच्छी तरह से काम करती है।

कवरिंग इंडेक्स पर कुछ अच्छे लिंक दिए गए हैं:

चेतावनी

यदि दोस्ती आपसी नहीं है, तो आपके पास दूसरे प्रकार के रिश्ते के लिए आधार है: FOLLOWER

अगर friend_to friend_of का मित्र नहीं है, तो आप बस उस रिश्ते को तालिका से बाहर कर सकते हैं।

यदि आप सभी प्रकार के संबंधों को परिभाषित करना चाहते हैं, चाहे वे पारस्परिक हों या न हों, आप संभवतः निम्न तालिका लेआउट का उपयोग कर सकते हैं:

CREATE TABLE person
(
    person_id INT NOT NULL AUTO_INCREMENT,
    ...
    PRIMARY KEY (person_id)
);
CREATE TABLE relationship
(
    rel_id INT NOT NULL AUTO_INCREMENT,
    person_id1 INT NOT NULL,
    person_id2 INT NOT NULL,
    reltype_id TINYINT,
    PRIMARY KEY (rel_id),
    UNIQUE KEY outer_affinity (reltype_id,person_id1,person_id2),
    UNIQUE KEY inner_affinity (reltype_id,person_id2,person_id1),
    KEY has_relationship_to (person1_id,reltype_id),
    KEY has_relationship_by (person2_id,reltype_id)
);
CREATE TABLE relation
(
    reltype_id TINYINT NOT NULL AUTO_INCREMENT,
    rel_name VARCHAR(20),
    PRIMARY KEY (reltype_id),
    UNIQUE KEY (rel_name)
);
INSERT INTO relation (relation_name) VALUES
('friend'),('follower'),('foe'),
('forgotabout'),('forsaken'),('fixed');

संबंध तालिका से, आप निम्नलिखित को शामिल करने के लिए रिश्तों की व्यवस्था कर सकते हैं:

  • दोस्तों आपसी मेलजोल होना चाहिए
  • शत्रु परस्पर हो सकते हैं या नहीं
  • अनुयायी परस्पर हो सकते हैं या नहीं
  • अन्य रिश्ते व्याख्या के अधीन होंगे (भूल या भूल गए या बदला लेने वाले (निश्चित) के प्राप्तकर्ता)
  • पोसिबी रिश्तों को और बढ़ाया जा सकता है

यह सभी रिश्तों के लिए अधिक मजबूत होना चाहिए, चाहे रिश्ता आपसी हो या न हो।


hi @rolandomysqldba, मैं आपके जवाबों का बहुत बड़ा प्रशंसक हूँ। मेरे लिए वास्तव में मददगार (इस मामले में 1 उदाहरण)। अब यहाँ मेरे लिए एक चेतावनी है, मुझे अनोखा रिश्ता चाहिए। (उदाहरण। यदि उपयोगकर्ता A के साथ B, तब A के साथ B मित्र स्वीकार्य नहीं है।) क्या मुझे ट्रिगर करना चाहिए? और प्रदर्शन के बारे में क्या? क्योंकि मेरे पास बहुत बड़ी तालिका (लगभग 1 मिलियन रिकॉर्ड) है, और यदि मैं उपयोगकर्ता के दोस्तों की खोज करता हूं (A केवल एक इंडेक्स का उपयोग करके दोनों (friend_of, friend_to) फ़ील्ड में संग्रहीत किया जाता है, और mysql, तो यह बहुत धीमी गति से प्रदर्शन कर रहा है। मुझे अपनी तालिका में डुप्लिकेट प्रविष्टियों को संग्रहीत करना होगा (जैसे। ए-> बी, बी-> ए)। कोई बेहतर विकल्प?
मनीष सपकाल

1

यदि आप उस एप्लिकेशन के भीतर नियंत्रण कर सकते हैं जो A की आईडी हमेशा B की आईडी से कम है (पूर्व आदेश A, B तत्व आईडी) तो आप बिना किसी से पूछे लाभ उठा सकते हैं (चयन करें जहां id_A = a और id_B = b, पूछने के बजाय (id_A = a और id_B = b) या (id_A = b AND id_B = a)), और अन्य रिकॉर्डों के साथ आपको जिन अभिलेखों की आवश्यकता होगी, उनमें से आधे को भी बनाए रखना होगा। फिर आपको रिश्ते की स्थिति बनाए रखने के लिए एक और फ़ील्ड का उपयोग करना चाहिए (जैसे-दोस्त, एक-सॉलिटेड-टू-बी, बी-सॉलिसिटेड-टू-ए, एक्सफ़िलेंड्स-ए, एक्सफ़िलेंड्स-बी), और आप कर रहे हैं।

यह वह तरीका है जिससे मैंने अपनी मैत्री प्रणाली को प्रबंधित किया है, और यह प्रणाली को सरल करता है और अन्य प्रणालियों के साथ आपकी ज़रूरत की आधी पंक्तियों का उपयोग करता है, केवल यह कहना कि A कोड में निम्न आईडी मान के बराबर है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.