2016-12-23 8 views
6

देखते हुए हमारे पास निम्न नियो 4j स्कीमा है (सरलीकृत लेकिन यह महत्वपूर्ण बिंदु दिखाता है)। दो प्रकार के नोड NODE और VERSION हैं। VERSION एस NODE से VERSION_OF संबंधों के माध्यम से जुड़े हुए हैं। VERSION नोड्स में दो गुण from और until हैं जो वैधता टाइमपैन को इंगित करते हैं - असीमित को इंगित करने के लिए या तो दोनों NULL (Neo4j शर्तों में nonexistent) हो सकते हैं। NODE एस HAS_CHILD रिश्ते के माध्यम से जोड़ा जा सकता है। दोबारा इन रिश्तों में दो गुण from और until हैं जो वैधता समय सीमा को दर्शाते हैं - असीमित को इंगित करने के लिए या तो दोनों NULL (Neo4j शर्तों में nonexistent) हो सकते हैं।नियो 4j साइफर क्वेरी नोड्स को खोजने के लिए जो बहुत धीमी नहीं हैं

संपादित: VERSION नोड्स और HAS_CHILD संबंधों पर वैधता दिनांक स्वतंत्र हैं (भले ही उदाहरण संयोग से पता चलता उन्हें गठबंधन जा रहा है)।

enter image description here

उदाहरण दो NODE रों एक और बी को दर्शाता है। एक दो VERSION रों AV1 6/30/17 तक और AV2 से 7/1/17 जबकि बी केवल एक संस्करण BV1 कि असीमित है शुरू कर दिया है। बी से HAS_CHILD संबंध 6/30/17 तक रिश्ते से जुड़ा हुआ है।

अब चुनौती उन सभी नोड्स के लिए ग्राफ से पूछना है जो बच्चे (जो रूट नोड्स हैं) समय पर एक विशिष्ट पल पर नहीं हैं। ऊपर दिए गए उदाहरण को देखते हुए, क्वेरी को बी वापस करना चाहिए यदि क्वेरी दिनांक उदा। 6/1/17, लेकिन यह बी और वापस करना चाहिए यदि क्वेरी दिनांक उदा। 8/1/17 (क्योंकि बी का कोई बच्चा 7/1/17 के रूप में नहीं है)।

वर्तमान क्वेरी आज मोटे तौर पर यह है कि एक के समान है:

MATCH (n1:NODE) 
OPTIONAL MATCH (n1)<-[c]-(n2:NODE), (n2)<-[:VERSION_OF]-(nv2:ITEM_VERSION) 
WHERE (c.from <= {date} <= c.until) 
AND (nv2.from <= {date} <= nv2.until) 
WITH n1 WHERE c IS NULL 
MATCH (n1)<-[:VERSION_OF]-(nv1:ITEM_VERSION) 
WHERE nv1.from <= {date} <= nv1.until 
RETURN n1, nv1 
ORDER BY toLower(nv1.title) ASC 
SKIP 0 LIMIT 15 

इस क्वेरी सामान्य रूप में अपेक्षाकृत ठीक काम करता है, लेकिन यह नरक के रूप में धीमी गति से हो रही है जब बड़े डेटा सेट (वास्तविक उत्पादन डेटासेट की तुलना में) पर इस्तेमाल शुरू होता है। 20-30k NODE एस (और VERSION एस की संख्या से दोगुना) के साथ (असली) क्वेरी मैक ओएस एक्स पर चल रहे एक छोटे डॉकर कंटेनर पर लगभग 500-700 एमएस लेती है) जो स्वीकार्य है। लेकिन 1.5 एम NODE एस (और VERSION एस की संख्या से दोगुना) के साथ (वास्तविक) क्वेरी एक नंगे धातु सर्वर पर 1 मिनट से थोड़ा अधिक समय लेती है (नियो 4j से कुछ और नहीं चलती)। यह वास्तव में स्वीकार्य नहीं है।

क्या हमारे पास इस क्वेरी को ट्यून करने का कोई विकल्प है? क्या NODE के संस्करण को संभालने के बेहतर तरीके हैं (जो मुझे संदेह है कि यहां प्रदर्शन समस्या है) या रिश्तों की वैधता? मुझे पता है कि संबंध गुणों को अनुक्रमित नहीं किया जा सकता है, इसलिए इन रिश्तों की वैधता को संभालने के लिए एक बेहतर स्कीमा हो सकती है।

कोई भी मदद या यहां तक ​​कि थोड़ी सी भी संकेत की सराहना की जाती है। answer from Michael Hunger के बाद

संपादित करें:

  1. जड़ नोड्स का प्रतिशत:

    वर्तमान उदाहरण डेटा सेट (1.5 नोड्स) परिणाम सेट 2k के बारे में अधिक पंक्तियां हैं साथ

    । यह 1% से कम है। पहले MATCH में

  2. ITEM_VERSION नोड:

    हम प्रयोग कर रहे हैं ITEM_VERSIONnv2 परिणाम ITEM नोड्स दी गई तारीख पर अन्य ITEM नोड्स कोई संबंध नहीं है कि करने के लिए सेट फिल्टर करने के लिए। इसका मतलब है कि या तो कोई संबंध मौजूद नहीं होना चाहिए जो दी गई तारीख के लिए मान्य है या कनेक्ट किए गए आइटम में ITEM_VERSION नहीं होना चाहिए जो दी गई तिथि के लिए मान्य है। मैं इस वर्णन करने के लिए कोशिश कर रहा हूँ:

    // date 6/1/17 
    
    // n1 returned because relationship not valid 
    (nv1 ...)->(n1)-[X_HAS_CHILD ...6/30/17]->(n2)<-(nv2 ...) 
    
    // n1 not returned because relationship and connected item n2 valid 
    (nv1 ...)->(n1)-[X_HAS_CHILD ...]->(n2)<-(nv2 ...) 
    
    // n1 returned because connected item n2 not valid even though relationship is valid 
    (nv1 ...)->(n1)-[X_HAS_CHILD ...]->(n2)<-(nv2 ...6/30/17) 
    
  3. संबंध-प्रकार का कोई उपयोग:

    समस्या यहां है कि सॉफ्टवेयर उपयोगकर्ता परिभाषित स्कीमा सुविधाओं और ITEM नोड्स कस्टम संबंध-प्रकार से जुड़े हुए हैं है । चूंकि हमारे रिश्ते पर कई प्रकार/लेबल नहीं हो सकते हैं, इस तरह के रिश्तों के लिए एकमात्र आम विशेषता यह है कि वे सभी X_ से शुरू होते हैं। यहां सरलीकृत उदाहरण से बाहर रखा गया है। भविष्यवाणी type(r) STARTS WITH 'X_' के साथ खोज रहे हैं यहां मदद करें?

+0

वहाँ एक के बीच कोई सहसंबंध है: संस्करण नोड से और तारीखें जब तक है, और से और HAS_CHILD रिश्तों पर दिनांक तक? अगर वे संरेखित, यह बेहतर हो सकता है रिश्ते प्रासंगिक हो करने के लिए: संस्करण नोड्स। – InverseFalcon

+0

@InverseFalcon सं रिश्ते और नोड्स पर "संस्करण" स्वतंत्र है। शायद उदाहरण यह स्पष्ट करने के लिए सबसे अच्छा नहीं है क्योंकि ** एवी 1 ** के लिए संस्करण वैधता संयोग से 'HAS_CHILD' संबंध के समान है। लेकिन ये मनमानी तिथियां हो सकती हैं। –

+0

यदि आप जानते हैं कि आप कौन से रिला-प्रकार खोजना चाहते हैं तो आप उन्हें सभी को स्पष्ट रूप से सूचीबद्ध कर सकते हैं, जैसे- - [: X_FOO |: X_BAR *] -> ' –

उत्तर

1

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

अभी दिनांक/समय गुणों के साथ आपके ग्राफ़ में एकमात्र नोड्स हैं: ITEM_VERSION नोड्स, तो चलो उनसे शुरू करें। आपको एक इंडेक्स की आवश्यकता होगी: ITEM_VERSION के तेज़ लुकअप के लिए गुणों से और जब तक।

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

मैं से में और न्यूनतम और अधिकतम मान के साथ जब तक आपके nulls को बदलने के लिए है, जो आपको सूचकांक देखने से नोड्स खोजने का लाभ लेने देना चाहिए के लिए प्रोत्साहित करेंगे:

MATCH (version:ITEM_VERSION) 
WHERE version.from <= {date} <= version.until 
MATCH (version)<-[:VERSION_OF]-(node:NODE) 
... 

कि कम से कम के लिए त्वरित पहुँच प्रदान करना चाहिए आपकी क्वेरी जारी रखने के लिए शुरुआत में नोड्स का एक छोटा सबसेट।

+1

आपकी प्रतिक्रिया के लिए धन्यवाद। 'ITEM_VERSION'-पहला दृष्टिकोण के बारे में आपका विचार उचित लगता है। आप अनुक्रमण के बारे में भी सही हैं - यह पहले ही हो चुका है। 'से' और' तक' गुणों के लिए भी सही है - वे क्रमशः न्यूनतम और अधिकतम मान के रूप में '0' और' 9999123' का उपयोग करते हैं। यह 'version.from <= {date} <= version.until' साथ सीमा स्कैन के लिए अनुमति देता है। तिथियां आम तौर पर इस पूर्णांक प्रारूप में संग्रहीत होती हैं (और तिथि/समय स्ट्रिंग के रूप में नहीं)। –

1

क्या आप Neo4j संस्करण का उपयोग कर रहे हैं।

आपके 1.5 एम नोड्स का प्रतिशत आपकी उदाहरण तिथि पर जड़ के रूप में मिलेगा, और यदि आपके पास सीमा नहीं है तो कितना डेटा वापस आता है? शायद यह मुद्दा मैच में इतनी ज्यादा नहीं है जितना अंत में छंटनी में?

मुझे यकीन है कि क्यों आप अपने पहले भाग में संस्करण नोड्स था नहीं कर रहा हूँ, कम से कम आप उन्हें के रूप में एक रूट नोड निर्धारित करने के लिए प्रासंगिक का वर्णन नहीं है।

आप रिश्ते-प्रकार का उपयोग नहीं किया।

MATCH (n1:NODE) // matches 1.5M nodes 
// has to do 1.5M * degree optional matches 
OPTIONAL MATCH (n1)<-[c:HAS_CHILD]-(n2) WHERE (c.from <= {date} <= c.until) 
WITH n1 WHERE c IS NULL 
// how many root nodes are left? 
// # root nodes * version degree (1..2) 
MATCH (n1)<-[:VERSION_OF]-(nv1:ITEM_VERSION) 
WHERE nv1.from <= {date} <= nv1.until 
// has to sort all those 
WITH n1, nv1, toLower(nv1.title) as title 
RETURN n1, nv1 
ORDER BY title ASC 
SKIP 0 LIMIT 15 
संबंधित मुद्दे