9

मेरे पास मेरे संबंध डेटाबेस (फायरबर्ड) में दो टेबल edge और node (आसन्नता सूची मॉडल) के साथ एक डीएजी है। मैं उन्हें बार-बार पूछना चाहता हूं, लेकिन रिकर्सिव क्वेरी बहुत अक्षम हैं। तो मैंने दांग et.al के बाद संक्रमणीय बंद रखने के लिए ट्रिगर्स को लागू करने की कोशिश की। कागज http://homepages.inf.ed.ac.uk/libkin/papers/tc-sql.pdfएक ट्रांजिटिव क्लोजर टेबल को कुशलता से कैसे बनाए रखें?

SELECT एस अब बहुत तेज़ हैं, लेकिन DELETE एस बेहद धीमी हैं, क्योंकि लगभग पूरे ग्राफ को एक ही डिलीट के लिए कॉपी किया गया है। इससे भी बदतर, समवर्ती अद्यतन असंभव प्रतीत होते हैं।

क्या इसे लागू करने का कोई बेहतर तरीका है?

संपादित

मैं कुछ प्रयोग किया था और टीसी तालिका के लिए एक संदर्भ काउंटर की शुरुआत की। इसके साथ, हटाए गए तेज़ हैं। मैंने कुछ सरल परीक्षण मामलों को लिखा, लेकिन मुझे यकीन नहीं है कि मैं सही कर रहा हूं। यह मैं अब तक है:

CREATE GENERATOR graph_tc_seq; 

CREATE TABLE EDGE (
    parent DECIMAL(10, 0) NOT NULL, 
    child DECIMAL(10, 0) NOT NULL, 
    PRIMARY KEY (parent, child) 
); 

CREATE TABLE GRAPH_TC (
    parent DECIMAL(10, 0) NOT NULL, 
    child DECIMAL(10, 0) NOT NULL, 
    refcount DECIMAL(9, 0), 
    PRIMARY KEY (parent, child) 
); 

CREATE TABLE GRAPH_TC_TEMP (
    session_id DECIMAL(9, 0), 
    parent DECIMAL(10, 0), 
    child DECIMAL(10, 0) 
); 

CREATE PROCEDURE GRAPH_TC_CREATE (p_parent DECIMAL(10, 0), c_child DECIMAL(10, 0)) 
AS 
    declare variable tp_parent DECIMAL(10,0); 
    declare variable tc_child DECIMAL(10,0); 
    declare variable session_id DECIMAL(9,0); 
    declare variable refs DECIMAL(9,0); 
begin 
    session_id = gen_id(graph_tc_seq,1); 
    insert into graph_tc_temp (parent, child, session_id, refcount) values (:p_parent, :p_parent, :session_id, 1); 
    insert into graph_tc_temp (parent, child, session_id, refcount) values (:c_child, :c_child, :session_id, 1); 
    insert into graph_tc_temp (parent, child, session_id, refcount) values (:p_parent, :c_child, :session_id, 1); 
    insert into graph_tc_temp (parent, child, session_id, refcount) select distinct :p_parent, child, :session_id, refcount from graph_tc where parent = :c_child and not parent = child; 
    insert into graph_tc_temp (child, parent, session_id, refcount) select distinct :c_child, parent, :session_id, refcount from graph_tc where child = :p_parent and not parent = child; 
    insert into graph_tc_temp (parent, child, session_id, refcount) select distinct a.parent, b.child, :session_id, a.refcount*b.refcount from graph_tc a, graph_tc b where a.child = :p_parent and b.parent = :c_child and not a.parent = a.child and not b.parent = b.child; 
    for select parent, child, refcount from graph_tc_temp e where session_id= :session_id and exists (select * from graph_tc t where t.parent = e.parent and t.child = e.child) into :tp_parent, :tc_child, :refs do begin 
     update graph_tc set refcount=refcount+ :refs where parent = :tp_parent and child = :tc_child; 
    end 
    insert into graph_tc (parent, child, refcount) select parent, child, refcount from graph_tc_temp e where session_id = :session_id and not exists (select * from graph_tc t where t.parent = e.parent and t.child = e.child); 
    delete from graph_tc_temp where session_id = :session_id; 
end^

CREATE PROCEDURE GRAPH_TC_DELETE (p_parent DECIMAL(10, 0), c_child DECIMAL(10, 0)) 
AS 
    declare variable tp_parent DECIMAL(10,0); 
    declare variable tc_child DECIMAL(10,0); 
    declare variable refs DECIMAL(9,0); 
begin 
    delete from graph_tc where parent = :p_parent and child = :p_parent and refcount <= 1; 
    update graph_tc set refcount = refcount - 1 where parent = :p_parent and child = :p_parent and refcount > 1; 
    delete from graph_tc where parent = :c_child and child = :c_child and refcount <= 1; 
    update graph_tc set refcount = refcount - 1 where parent = :c_child and child = :c_child and refcount > 1; 
    delete from graph_tc where parent = :p_parent and child = :c_child and refcount <= 1; 
    update graph_tc set refcount = refcount - 1 where parent = :p_parent and child = :c_child and refcount > 1; 
    for select distinct :p_parent, b.child, refcount from graph_tc b where b.parent = :c_child and not b.parent = b.child into :tp_parent, :tc_child, :refs do begin 
     delete from graph_tc where parent = :tp_parent and child = :tc_child and refcount <= :refs; 
     update graph_tc set refcount = refcount - :refs where parent = :tp_parent and child = :tc_child and refcount > :refs; 
    end 
    for select distinct :c_child, b.parent, refcount from graph_tc b where b.child = :p_parent and not b.parent = b.child into :tc_child, :tp_parent, :refs do begin 
     delete from graph_tc where child = :tc_child and parent = :tp_parent and refcount <= :refs; 
     update graph_tc set refcount = refcount - :refs where child = :tc_child and parent = :tp_parent and refcount > :refs; 
    end 
    for select distinct a.parent, b.child, a.refcount*b.refcount from graph_tc a, graph_tc b where not a.parent = a.child and not b.parent = b.child and a.child = :p_parent and b.parent = :c_child into :tp_parent, :tc_child, :refs do begin 
     delete from graph_tc where parent = :tp_parent and child = :tc_child and refcount <= :refs; 
     update graph_tc set refcount = refcount - :refs where parent = :tp_parent and child = :tc_child and refcount > :refs; 
    end 
end^

CREATE TRIGGER GRAPH_TC_AFTER_INSERT FOR EDGE AFTER INSERT as 
begin 
    execute procedure graph_tc_create(new.parent,new.child); 
end^

CREATE TRIGGER GRAPH_TC_AFTER_UPDATE FOR EDGE AFTER UPDATE as 
begin 
    if ((new.parent <> old.parent) or (new.child <> old.child)) then begin 
    execute procedure graph_tc_delete(old.parent,old.child); 
    execute procedure graph_tc_create(new.parent,new.child); 
    end 
end^

CREATE TRIGGER GRAPH_TC_AFTER_DELETE FOR EDGE AFTER DELETE as 
begin 
    execute procedure graph_tc_delete(old.parent,old.child); 
end^

यह मेरे अपने विचार है, लेकिन मुझे लगता है कि दूसरों को एक टीसी को लागू किया है पहले से ही। क्या वे वही काम कर रहे हैं?

मेरे पास कुछ परीक्षण मामले हैं, लेकिन मुझे यकीन नहीं है कि मुझे बड़े ग्राफ के साथ असंगतता मिल सकती है।

समेकन के बारे में, मुझे लगता है कि यह दृष्टिकोण असफल हो जाएगा जब दो एक साथ लेन-देन ग्राफ को अपडेट करना चाहते हैं, है ना?

संपादित

मैं अपने कोड में कुछ कीड़े पाया, और मैं आपके साथ तय संस्करण साझा करना चाहते हैं।

मुझे एक अच्छा लेख मिला: http://www.codeproject.com/Articles/22824/A-Model-to-Represent-Directed-Acyclic-Graphs-DAG-o। क्या अलग-अलग दृष्टिकोणों के साथ और अधिक दिलचस्प लेख या वैज्ञानिक पत्र हैं?

+0

क्या आप डीडीएल के प्रासंगिक (भागों) को शामिल कर सकते हैं और परिभाषाओं को ट्रिगर कर सकते हैं? –

+0

@MarkRotteveel मेरा संपादन देखें –

+2

एक [जीटीटी (वैश्विक अस्थायी तालिका)] (http://www.firebirdsql.org/file/documentation/reference_manuals/reference_material/html/langrefupd25-ddl-table.html) का उपयोग करने पर विचार करें 'GRAPH_TC_TEMP' –

उत्तर

1

मैंने यहां वर्णित ट्रांजिटिव रिफ्लेक्सिव क्लोजर टेबल मॉडल को विस्तारित करके धीमे डिलीट ऑपरेशन को ठीक किया है: http://www.dba-oracle.com/t_sql_patterns_incremental_eval.htm। इसमें पथों की गिनती पूरी तरह से बनाए रखने के लिए थोड़ा और काम हुआ, लेकिन जब यह हटा दिया गया तो यह अलग हो गया जब डिलीट 6 सेकंड से प्रत्येक व्यक्तिगत निकालने के ऑपरेशन को लापरवाह करने के लिए चला गया (अब मैं ग्राफ में हर रिश्ते को हटा सकता हूं, और फिर उन्हें वापस जोड़ सकता हूं 4,000 रिश्तों के लिए कुल 14 सेकंड में)।

+0

और बोनस के लिए, पथों की कुल गणना के समान ही सबसे छोटी पथ लंबाई को बनाए रखा जा सकता है http://www.tjhsst.edu/~rlatimer/acm/DatabaseSystems/ShortestDistanceinFirstOrderLogicSQLp698-pangTODS-Oct05.pdf – nclu

4

एसक्यूएल ग्राफ से निपटने के लिए सही उपकरण नहीं है। इनमें से किसी एक का उपयोग करें:

http://en.wikipedia.org/wiki/Graph_database

मैं बहुत ज्यादा ArangoDB पसंद है, जो एक syntaxe पास MongoDB किया है।

+0

मुझे पता है कि ग्राफ डीबी आदर्श समाधान होगा; लेकिन <100k किनारों के साथ दो ग्राफ के लिए मैं एक नया डेटाबेस नहीं जोड़ता हूं। –

0

बनाने का प्रयास करें प्रासंगिक के लिए अनुक्रमित जहां खंड (उदा .: child, parent)।

मैं फायरबर्ड से परिचित नहीं हूं, लेकिन देखो कि "फायरबर्ड वर्णन" इस पर कैसे काम करता है और जांचें कि यह आपके प्रक्रियाओं में आपके द्वारा चुने गए चयनों को गति देने के लिए इंडेक्स के उचित उपयोग का उपयोग कर रहा है या नहीं।

यहां तक ​​कि आपके मामले में अपडेटडेट/डिलीट/डालने के लिए प्रदर्शन में खोए गए इंडेक्स को भी बनाते हुए, यह परिणाम में सुधार कर सकता है।

+0

वास्तविक कार्यान्वयन में सूचकांक हैं; मैंने उपरोक्त कोड में 'CREATE INDEX' कथन की प्रतिलिपि नहीं बनाई है। –

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