2009-05-10 19 views
15

मेरे पास एक सीएमएस है जो लेखों के खिलाफ टिप्पणियां संग्रहीत करता है। ये टिप्पणियां थ्रेडेड और गैर थ्रेडेड दोनों हो सकती हैं। यद्यपि तकनीकी रूप से वे वही हैं, जब उत्तर थ्रेड नहीं होता है तो उत्तर कॉलम खाली छोड़ दिया जाता है। मेरा एप्लिकेशन sqlLite, MySQL और pgsql पर काम करता है इसलिए मुझे काफी मानक SQL की आवश्यकता है।पेड़ डेटा संग्रहीत करने की तेज़ रिलेशनशिप विधि (उदाहरण के लिए लेखों पर थ्रेडेड टिप्पणियां)

मैं वर्तमान में एक टिप्पणी तालिका

comment_id 
article_id 
user_id 
comment 
timestamp 
thread (this is the reply column) 

मेरा प्रश्न यह पता लगाने की कैसे सबसे अच्छा डेटाबेस में पिरोया टिप्पणियों का प्रतिनिधित्व करने के है। शायद एक अलग टेबल में जो सामग्री के बिना पेड़ सेट का समर्थन करता है और पाठ को पकड़ने के लिए एक साधारण तालिका का समर्थन करता है? शायद जिस तरह से यह पहले से ही है? शायद एक और तरीका?

यदि टिप्पणियां अन-थ्रेडेड हैं तो मैं आसानी से टाइमस्टैम्प द्वारा ऑर्डर कर सकता हूं।

वे इस

ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1)) 

तरह तरह मैं पिरोया रहे हैं, तो आप आदेश द्वारा से देख सकते हैं, टिप्पणी प्रश्नों हमेशा की तरह समारोह आधारित अनुक्रमित केवल वास्तव में ओरेकल में रहते हैं एक सूचकांक का उपयोग नहीं होगा। मुझे तेज टिप्पणी पृष्ठों को हल्का करने में मदद करें।

उत्तर

19

मुझे वास्तव में यह पसंद है कि Drupal इस समस्या को हल करता है। यह प्रत्येक टिप्पणी के लिए एक थ्रेड आईडी असाइन करता है। यह आईडी पहली टिप्पणी के लिए 1 से शुरू होती है। अगर इस टिप्पणी में कोई जवाब जोड़ा गया है, तो आईडी 1.1 इसे सौंपा गया है। 1.1 पर टिप्पणी का उत्तर थ्रेड आईडी 1.1.1 दिया गया है। टिप्पणी का एक भाई 1.1 को थ्रेड आईडी 1.2 दिया गया है। तुम्हें नया तरीका मिल गया है। जब कोई टिप्पणी जोड़ दी जाती है तो इन थ्रेड आईडी की गणना एक क्वेरी के साथ आसानी से की जा सकती है।

जब थ्रेड प्रदान किया जाता है, तो थ्रेड से संबंधित सभी टिप्पणियां थ्रेड आईडी द्वारा क्रमबद्ध एक क्वेरी में लाई जाती हैं। यह आपको आरोही क्रम में धागे देता है। इसके अलावा, थ्रेड आईडी का उपयोग करके, आप प्रत्येक टिप्पणी का घोंसला स्तर पा सकते हैं, और तदनुसार इसे इंडेंट कर सकते हैं।

1 
1.1 
1.1.1 
1.2 
1.2.1 

सुलझाने के लिए कुछ मुद्दों के होते हैं: धागा आईडी के एक घटक 2 अंक तक बढ़ता है

  • हैं, धागा आईडी द्वारा छँटाई की उम्मीद आदेश का उत्पादन नहीं होगा। एक आसान समाधान यह सुनिश्चित कर रहा है कि थ्रेड आईडी के सभी घटकों को समान चौड़ाई रखने के लिए शून्य से गद्देदार हैं।
  • अवरोही थ्रेड आईडी द्वारा छंटनी अपेक्षित अवरोही क्रम उत्पन्न नहीं करती है।

ड्रूपल वानकोड नामक एक संख्या प्रणाली का उपयोग करके एक और जटिल तरीके से पहला मुद्दा हल करता है। दूसरे मुद्दे के लिए, अवरोही क्रम द्वारा सॉर्ट करते समय इसे बैकस्लैश (जिसका ASCII कोड अंक से अधिक है) को जोड़कर हल किया जाता है। आप comments module के स्रोत कोड की जांच करके इस कार्यान्वयन के बारे में अधिक जानकारी प्राप्त कर सकते हैं (फ़ंक्शन टिप्पणी_get_thread से पहले बड़ी टिप्पणी देखें)।

2

मैंने यह वास्तव में किया, वास्तव में! मैंने एक संबंधपरक डेटाबेस में पदानुक्रमित डेटा का प्रतिनिधित्व करने के नेस्टेड सेट मॉडल का उपयोग किया।

Managing Hierarchical Data in MySQL मेरे लिए शुद्ध सोना था। नेस्टेड सेट उस आलेख में वर्णित दूसरा मॉडल हैं।

+0

वाह जो तेज़ था। –

+0

नेस्टेड सेट के बारे में क्या बेकार है कि पेड़ की संरचना को किसी भी तरह से संशोधित करना महंगा है – acjay

0

असल में, इसे पढ़ने और लिखने के बीच संतुलन होना चाहिए।

यदि आप प्रत्येक डालने पर पंक्तियों का एक समूह अद्यतन करने के साथ ठीक हैं, तो नेस्टेड सेट (या समकक्ष) आपको आसान, तेज़ पढ़ेगा।

इसके अलावा, माता-पिता पर एक साधारण एफके आपको अति-सरल डालने देगा, लेकिन पुनर्प्राप्ति के लिए एक दुःस्वप्न हो सकता है।

मुझे लगता है कि मैं नेस्टेड सेट के साथ जाऊंगा, लेकिन अपेक्षित डेटा वॉल्यूम और उपयोग पैटर्न के बारे में सावधान रहें (प्रत्येक प्रविष्टि के लिए दो अनुक्रमित कॉलम (बाएं और दाएं जानकारी के लिए) पर कई, शायद कई, पंक्तियां अपडेट करना किसी बिंदु पर एक समस्या हो सकती है)।

2

आपके पास आसन्नता और नेस्टेड सेट मॉडल के बीच एक विकल्प है। आलेख Managing Hierarchical Data in MySQL एक अच्छा परिचय के लिए बनाता है।

सैद्धांतिक चर्चा के लिए, सेल्को के Trees and Hierarchies देखें।

यदि आपका डेटाबेस विंडोिंग फ़ंक्शंस का समर्थन करता है तो थ्रेडेड सूची को कार्यान्वित करना आसान है।

create Tablename (
    RecordID integer not null default 0 auto_increment, 
    ParentID integer default null references RecordID, 
    ... 
) 

फिर आप एक पिरोया दृश्य प्रदर्शित करने के लिए एक पुनरावर्ती आम तालिका अभिव्यक्ति का उपयोग कर सकते हैं: आप सभी की जरूरत के रूप में अपने लक्ष्य डेटाबेस तालिका में एक पुनरावर्ती संदर्भ, है। एक उदाहरण here उपलब्ध है।

2

दुर्भाग्यवश, इसे करने के लिए शुद्ध SQL विधियां काफी धीमी हैं।

@Marc W द्वारा प्रस्तावित काफी सुरुचिपूर्ण हैं, लेकिन यदि आपकी पेड़ की शाखाएं श्रेणियों को हिट करती हैं तो उन्हें पूरे पेड़ को अपडेट करने की आवश्यकता हो सकती है, जो काफी धीमी हो सकती है।

कैसे MySQL में तेजी से यह करने के लिए पर अपने ब्लॉग में इस लेख देखें:

आप एक समारोह बनाने की आवश्यकता होगी:

CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT 
NOT DETERMINISTIC 
READS SQL DATA 
BEGIN 
     DECLARE _id INT; 
     DECLARE _parent INT; 
     DECLARE _next INT; 
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL; 

     SET _parent = @id; 
     SET _id = -1; 

     IF @id IS NULL THEN 
       RETURN NULL; 
     END IF; 

     LOOP 
       SELECT MIN(id) 
       INTO @id 
       FROM t_hierarchy 
       WHERE parent = _parent 
         AND id > _id; 
       IF @id IS NOT NULL OR _parent = @start_with THEN 
         SET @level = @level + 1; 
         RETURN @id; 
       END IF; 
       SET @level := @level - 1; 
       SELECT id, parent 
       INTO _id, _parent 
       FROM t_hierarchy 
       WHERE id = _parent; 
     END LOOP; 
END 

और इसे इस तरह की क्वेरी में उपयोग करें:

SELECT hi.* 
FROM (
     SELECT hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level 
     FROM (
       SELECT @start_with := 0, 
         @id := @start_with, 
         @level := 0 
       ) vars, t_hierarchy 
     WHERE @id IS NOT NULL 
     ) ho 
JOIN t_hierarchy hi 
ON  hi.id = ho.id 

यह निश्चित रूप से MySQL विशिष्ट है लेकिन यह वास्तविक तेज़ है।

आप इस PostgreSQL और MySQL betwen पोर्टेबल होना चाहते हैं, तो आप CONNECT BY के लिए PostgreSQL के योगदान का उपयोग करें और दोनों प्रणालियों के लिए एक ही नाम के साथ एक संग्रहीत प्रक्रिया में क्वेरी लपेट कर सकते हैं।

4

मैं जानता हूँ कि इस सवाल का जवाब देर से एक सा है, लेकिन पेड़ के लिए डेटा को बंद करने की मेज http://www.slideshare.net/billkarwin/models-for-hierarchical-data

यह 4 तरीकों का वर्णन करता है का उपयोग करें:

  • Adjcency सूची (सरल माता पिता विदेशी कुंजी)
  • पथ गणना (स्वीकार्य उत्तर में उल्लिखित ड्रूपल रणनीति)
  • नेस्टेड सेट
  • क्लोजर टेबल (भंडारण एसेस एक संभावित दूरी कॉलम के साथ एक अलग संबंध [टेबल] में टोर/वंशज तथ्य)

अंतिम विकल्प में बाकी की तुलना में आसान सीआरयूडी संचालन के फायदे हैं। लागत अंतरिक्ष है, जो सबसे खराब मामले में संख्या पेड़ नोड्स में ओ (एन^2) आकार है, लेकिन शायद अभ्यास में इतना बुरा नहीं है।

+0

बहुत अच्छा! क्लोजर टेबल काफी आशाजनक दिखता है। मूल उत्तर शायद संसाधन से वास्तविक जानकारी प्रदान करता है, न केवल संसाधन के लिए एक लिंक। मैंने मुख्य टेकवे शामिल करने के लिए संपादित किया है। – acjay

+0

@acjay ठीक है, धन्यवाद –