5

के लिए डेटाबेस को कैसे व्यवस्थित करें मैं डेटा की त्वरित पुनर्प्राप्ति के लिए डेटाबेस बुद्धि वर्चुअल ट्री व्यू और SQLite डेटाबेस को बनाने के लिए एक तरीका ढूंढ रहा हूं। वर्चुअल ट्री व्यू के साथ ऑनऑन इनिट इवेंट है, यह इस उद्देश्य के लिए हमेशा व्यावहारिक नहीं है।त्वरित नोड पहुंच

डेटा यूज़नेट न्यूज़ ग्रुप से प्राप्त किया जाता है और इसे थ्रेडेड करने की आवश्यकता होती है। थ्रेडिंग के लिए उपयोगी डेटा पोस्ट आईडी (int64, प्राथमिक कुंजी भी) है, संदर्भ (तार जो पिछली पोस्ट को थ्रेड में संदर्भित करते हैं)।

कार्यक्रम संदर्भों में तारों की खोज करता है और निर्धारित करता है कि इसे किस पोस्टिड में जाना चाहिए। इसलिए उदाहरण के पद id = 1234 के लिए है, तो अगले पोस्ट 1235 हो सकता है, और उसके बाद 1236 1234.

यहाँ एक संभव डेटाबेस उदाहरण है के जवाब हो सकता है:

post id references parent id 
    1234  .... ....  0 
    1235  .... ....  0 
    1236  .... ....  1234 

तो अब यह है कि यह कैसे सही दिखता है अभी व।

अब समस्या यह है कि तेजी से पुनर्प्राप्ति के लिए इस डेटा को कैसे व्यवस्थित किया जाए। यदि केवल रूट नोड है तो मैं डेटाबेस प्रविष्टियों के आधार पर रूटNodeCount असाइन कर सकता हूं और फिर OnNodeInit में अनुरोध के अनुसार उन्हें एक-एक करके पढ़ सकता हूं। उप-नोड्स होने पर मुझे किसी भी तरह डेटाबेस को पुनर्व्यवस्थित करने की आवश्यकता होती है ताकि यह पता चल सके कि कौन सा नोड खोला गया है, इस पर निर्भर करता है कि सबनोड कैसे तेजी से प्राप्त करें।

मैं उप-नोड की आईडी के साथ अतिरिक्त फ़ील्ड "has_subnodes" असाइन करने के बारे में सोच रहा था। जब कोई नोड क्लिक किया जाता है तो उस नोड और प्रत्येक लिंक किए गए नोड को पढ़ता है।

आप इस डेटाबेस को कैसे व्यवस्थित करेंगे ताकि इसे ऑननोडइनिट में अच्छी तरह से पढ़ा जा सके या आप उस घटना का बिल्कुल उपयोग करेंगे? AddChildNoInit() विधि का उपयोग करके नोड्स भी शुरू किए जा सकते हैं। किसी भी विचार या पॉइंटर्स का स्वागत किया जाएगा।

अद्यतन (और कैसे मैं इसे हल)

कुछ गैर virtualtreeview संबंधित जानकारी यहां उपलब्ध है: Implementing a hierarchical data structure in a database

क्या मैं कर संशोधित Preorder ट्री Traversal उपयोग कर रहा है में जानकारी संग्रहीत करने के समाप्त हो गया नोड्स के बारे में डेटाबेस और हर बार एक निश्चित नोड का अनुरोध किया जाता है:

ए) यह आंतरिक कैश में देखा जाता है जो मूल रूप से वर्चुअल ट्री व्यू संरचना के समान संरचना रखता है।

ख) यदि कैश में पाया, इस कैश प्रविष्टि हटा दिया जाता है (यह कभी नहीं 100 से अधिक आइटम)

ग) रखती है न मिलने पर, अतिरिक्त 100 आइटम कैश (50 अनुरोध किया नोड से ऊपर में जुड़ जाते हैं, और 50 नीचे)। यदि आवश्यक हो तो पाठ्यक्रम की इस संख्या को 500 या 1000 आइटम में संशोधित किया जा सकता है। डुप्लिकेट प्रविष्टियों को पढ़ने से बचने के लिए इसे देखने के लिए कुछ अतिरिक्त जांचें देखने के लिए कुछ अतिरिक्त चेक हैं।

डी) यदि मुझे और गति की आवश्यकता है, तो मैं डेटाबेस से अतिरिक्त तकनीक - लोड नोड्स को लागू कर सकता हूं, इस पर आधारित है कि उपयोगकर्ता वर्चुअलट्रीव्यू को कितना स्क्रॉल करता है - जैसा कि std :: vector स्मृति आवंटित करता है - पहले मैं केवल 100 नोड लोड करता हूं, फिर यदि उपयोगकर्ता बहुत स्क्रॉल करता है, मैं 200 लोड करता हूं, फिर 400 आदि ... जितना अधिक उपयोगकर्ता स्क्रॉल करता है तेज़ी से पूरे पेड़ को लोड करता है लेकिन फिर भी उसे लोड नहीं करता है अगर वह कभी स्क्रॉल नहीं करता है।

इस तरह, जो नोड्स कभी नहीं देखे जाते हैं वे डेटाबेस से कभी लोड नहीं होते हैं। यह माउस व्हील के साथ स्क्रॉल करने के लिए ठीक काम करता है (कभी-कभी छोटी देरी के साथ जब यह उस बिंदु को पास करता है जहां कैश खाली होता है और डिस्क से अधिक डेटा की आवश्यकता होती है) और तीर बटन/चाबियों के साथ स्क्रॉल करने के लिए।जब आप स्क्रॉलबार को कुछ स्थिति (नीचे से मध्य तक कहते हैं) पर खींचते हैं तो यह थोड़ी धीमी होती है, लेकिन इसकी अपेक्षा की जाती है क्योंकि डेटा तुरंत डिस्क से नहीं लाया जा सकता है।

यह सबसे अच्छा है अगर मैं पूर्व निर्धारित करता हूं कि मैं उन्हें लोड करने से पहले कैश/आइटम के लिए कितनी मेमोरी का उपयोग करना चाहता हूं, तो जितनी तेजी से स्क्रॉलिंग होती है, लेकिन निश्चित रूप से डेटा प्रदर्शित नहीं होने पर यह अधिक स्मृति का उपयोग करता है।

+2

अभिभावक। आपको मूल संदर्भ – OnTheFly

+0

मूल रूप से, सबसे सरल पेड़ की तरह डेटा में 'आईडी' और' पैरेंट आईडी 'है, जहां माता-पिता आईडी को इंगित करता है जो यह एक बच्चे के रूप में होता है। उचित पैरेंट नोड के तहत बाल नोड्स को रखना (सबसे सरल रूप में) को सभी मौजूदा नोड्स के माध्यम से पुनरावृत्ति की आवश्यकता होती है जब तक कि आपको पेरेंट आईडी के बराबर आईडी न मिल जाए। हालांकि सभी वर्चुअल ट्री व्यू नोड्स के माध्यम से फिर से चलना बहुत तेज़ है, लेकिन यह बहुत धीमा हो सकता है क्योंकि अधिक नोड्स जोड़े जाते हैं। एक विस्तृत विधि सभी नोड्स को फ्लैट सूची के रूप में जोड़ना होगा और फिर उन्हें उचित स्थितियों पर ले जाना होगा, हालांकि एल्गोरिदम थोड़ा और जटिल हो सकता है। – LightBulb

+0

@ लाइटबुल लेकिन फिर मैं पेड़ की पुण्यता खो देता हूं और उन्हें गतिशील रूप से नहीं जोड़ता? यदि बहुत सारे नोड्स और सबनोड हैं, तो अभी तक खोले गए लोगों को जोड़ने की कोई ज़रूरत नहीं है? – Coder12345

उत्तर

1

आप एक डेटाबेस में श्रेणीबद्ध डेटा स्टोर करने के लिए देख रहे हैं।
समस्या यह है कि एसक्यूएल इस तरह के डेटा से निपटने के लिए सुसज्जित नहीं है।

आपके पास कई समाधान हैं, जिनमें से प्रत्येक अपने विपक्ष और पेशेवरों के साथ हैं।

http://www.sitepoint.com/hierarchical-data-database/
http://www.sitepoint.com/hierarchical-data-database-2/

मेरा व्यक्तिगत पसंदीदा Modified Preorder Tree Traversal

यहाँ आप छोड़ दिया की दुकान और एक में डेटाबेस में सही नोड है:
यहाँ एक लिंक आप तरीकों में से प्रत्येक पर पढ़ना चाहते हैं है बहुत काउंटर अंतर्ज्ञानी तरीका, जो नोड्स को थोड़ा धीमा कर देता है, लेकिन पुनर्प्राप्ति बिजली तेजी से।

आप डेल्फी में अपने तर्क को कोड कर सकते हैं, लेकिन मैं पसंद के अपने डेटाबेस में संग्रहित प्रक्रियाओं का उपयोग करना पसंद करता हूं।
इस तरह डेल्फी में आपका तर्क सरल रहता है और यदि डेटाबेस आपके डेल्फी कोड को बदलना नहीं है। यदि आप चाहते हैं कि मैं संग्रहित प्रक्रियाओं के लिए SQL कोड शामिल कर सकता हूं, लेकिन अभी नहीं, क्योंकि वह कोड लैपटॉप पर नहीं है, तो अब मुझे मिल गया है।

+0

है, मुझे संशोधित प्रीऑर्डर ट्री ट्रैवर्सल भी पसंद है क्योंकि डेटा एक बार जोड़ा जाता है और फिर शायद ही कभी संशोधित किया जाता है लेकिन खोज काफी तेज होती है। – Coder12345

+0

इसके अलावा वंशावली विधि अच्छी तरह से काम करने लगती है - http://www.ferdychristant.com/blog/archive/DOMM-7QJPM7 - और यह डेविड चांडलर की पेटेंट विधि का उपयोग नहीं करती है (जो कि वैसे भी बाल नोड्स की परिवर्तनीय संख्या के लिए बेकार है) । – Coder12345

1

सबसे सुरुचिपूर्ण नहीं है लेकिन यह वह तरीका है जिसका उपयोग मैं अपने पेड़ को पॉप्युलेट करने के लिए करता हूं।

इसे केवल दो सरल प्रश्नों के लिए डेटा एसेस की आवश्यकता है, और बाकी सभी क्लाइंट पक्ष हैं।

यह आसानी से हजारों नोड्स लोड करेगा। (इसे अब देख, मैं शायद दूर सिर्फ एक क्वेरी के साथ मिल सकता है - अपनी एक सा पुराना!):

procedure TFrameComponentViewer.LoadComponentTree; 
var 
RootNodeData : PMasterComponent; 
CompQ,ParentQ : TMyQuery; 

procedure PopulateNodeData(Node: PVirtualNode;ComponentID : integer); 
var NodeData : PMasterComponent; 
begin 
    if CompQ.Locate('ComponentID',ComponentID,[loCaseInsensitive]) then 
    begin 
    NodeData := TreeComponents.GetNodeData(Node); 
    //Populate your desired TreeData 
    NodeData.ComponentID := CompQ.Fields[fldComponentID].AsInteger; 
    NodeData.ComponentCode := CompQ.Fields[fldComponentCode].AsString; 
    NodeData.ComponentType := CompQ.Fields[fldComponentType].AsInteger; 
    NodeData.IsPipeline := CompQ.Fields[fldComponentIsPipeline].AsBoolean; 
    NodeData.Description := CompQ.Fields[fldComponentDescription].AsString; 
    NodeData.StartKP := CompQ.Fields[fldComponentStartKP].AsFloat; 
    NodeData.EndKP := CompQ.Fields[fldComponentEndKP].AsFloat; 
    NodeData.Diameter := CompQ.Fields[fldComponentDiameter].AsFloat; 
    NodeData.WallThickness := CompQ.Fields[fldComponentWallThickness].AsFloat; 
    NodeData.CriticalSpanLength := CompQ.Fields[fldComponentCSL].AsFloat; 
    NodeData.Historical := CompQ.Fields[fldComponentHistorical].AsBoolean; 
    end; 
end; 

procedure AddNodesRecursive(ParentNode : PVirtualNode;ParentNodeID : Integer); 
var AddedNode : PVirtualNode; 
AddedNodeData : PMasterComponent; 
Children : Array of Integer; 
i : Integer; 
begin 
    try 
     ParentQ.Filtered := False; 
     ParentQ.Filter := 'Parent_ID = '+InttoStr(ParentNodeID); 
     ParentQ.Filtered := True; 
     ParentQ.First; 
     SetLength(Children,ParentQ.RecordCount); 
     for i:=0 to ParentQ.RecordCount-1 do 
     begin 
      Children[i] := ParentQ.Fields[0].AsInteger; 
      ParentQ.Next; 
     end; 
     for i:=0 to High(Children) do 
     begin 
      AddedNode := TreeComponents.AddChild(ParentNode); 
      AddedNodeData := TreeComponents.GetNodeData(AddedNode); 
      System.Initialize(AddedNodeData^); //initialize memory 
      PopulateNodeData(AddedNode,Children[i],CompQ); 
      AddNodesRecursive(AddedNode,AddedNodeData.ComponentID); 
     end; 
    finally 
    end; 
end; 

begin 
    TreeComponents.BeginUpdate; 
    treeComponents.Clear; 
    CompQ := TMyQuery.Create(nil); 
    ParentQ := TMyQuery.Create(nil); 
    try 
     CompQ.Connection := DataBaseline.BaseLineConnection; 
     CompQ.SQL.Add('SELECT * FROM Components'); 
     CompQ.Open; 
     ParentQ.Connection := DataBaseline.BaseLineConnection; 
     ParentQ.Close; 
     ParentQ.SQL.Clear; 
     ParentQ.SQL.Add('SELECT ComponentID,Parent_ID FROM Components ORDER BY OrderNo'); 
     ParentQ.Open; 
     RootNode := TreeComponents.AddChild(nil); 
     RootNodeData := TreeComponents.GetNodeData(RootNode); 
     System.Initialize(RootNodeData^); //initialize memory 
     RootNodeData.ComponentID := -1; 
     AddNodesRecursive(RootNode,-1); 
    finally 
    TreeComponents.EndUpdate; 
    TreeComponents.FullExpand; 
    CompQ.Close; 
    ParentQ.Close; 
    FreeandNil(CompQ); 
    FreeandNil(ParentQ); 
    end; 
end; 

नोट: OrderBy कॉलम वैकल्पिक है, मैं इसे की आवश्यकता के रूप में मेरे पेड़ आदेश विशिष्ट हैं।

तो डीबी इन तीन स्तंभ हैं, के साथ साथ किसी भी कस्टम डेटा की आवश्यकता:

ID, ParentID (-1 कोई माता-पिता के लिए), OrderNo

+0

यह समाधान अच्छी तरह से काम करेगा मैं वर्चुअल ट्री व्यू की योग्यता खोना नहीं चाहता हूं। जो मैं वर्तमान में उपयोग करता हूं वह कैश में आइटम जोड़ रहा है और फिर पहले OnNodeInit में कैश को देखता है और फिर यदि कैश पर्याप्त नहीं है और इसमें आवश्यक नोड नहीं है तो मैं संशोधित प्रीऑर्डर ट्री ट्रैवर्सल डेटा का उपयोग करके डेटाबेस से अधिक आइटम के साथ कैश भरता हूं। ऐसा लगता है कि यह जल्दी से काम करता है और पूरे पेड़ को उस डेटा के साथ लोड नहीं करता है जिसकी कभी आवश्यकता नहीं होती है। – Coder12345

+0

कोई समस्या नहीं, खुशी है कि आपके पास समाधान – Simon

संबंधित मुद्दे