تحسين الدُفعات ذات الحجم العالي في Neo4J باستخدام REST

StackOverflow https://stackoverflow.com/questions/19839469

سؤال

أحتاج إلى إدراج كمية هائلة من العقد مع العلاقات بينها في Neo4J عبر نقطة نهاية دفعة REST API ، حوالي 5K سجلات/S (لا تزال متزايدة).

سيكون هذا الإدراج المستمر 24 × 7. قد يتطلب كل سجل إنشاء عقدة واحدة فقط ، ولكن قد يتطلب الآخر عقدًا وعلاقة واحدة يتم إنشاؤها.

هل يمكنني تحسين أداء الإدراج عن طريق تغيير الإجراء الخاص بي أو تعديل إعدادات Neo4J؟

تقدمي حتى الآن:

1. لقد كنت أختبر مع Neo4J لفترة من الوقت ، لكنني لم أستطع الحصول على الأداء الذي احتاجه

مربع خادم الاختبار: 24 نوى + 32 جيجابايت ذاكرة الوصول العشوائي

NEO4J 2.0.0-M06 مثبت كخدمة مستقلة.

تشغيل تطبيق Java الخاص بي على نفس الخادم. (سيحتاج تطبيق Neo4J و Java إلى تشغيله على الخادم الخاص بهما في المستقبل ، لذلك لا يمكن استخدام الوضع المضمّن)

REST API نقطة النهاية: /dB /بيانات /دفعة (الهدف: /cypher)

باستخدام فهرس المخطط ، يقيد ، دمج ، إنشاء فريدة من نوعها.

2. مخططي:

neo4j-sh (0)$ schema
==> Indexes
==>   ON :REPLY(created_at)   ONLINE                             
==>   ON :REPLY(ids)          ONLINE (for uniqueness constraint) 
==>   ON :REPOST(created_at) ONLINE                             
==>   ON :REPOST(ids)        ONLINE (for uniqueness constraint) 
==>   ON :Post(userId)      ONLINE                             
==>   ON :Post(postId)    ONLINE (for uniqueness constraint) 
==> 
==> Constraints
==>   ON (post:Post) ASSERT post.postId IS UNIQUE
==>   ON (repost:REPOST) ASSERT repost.ids IS UNIQUE
==>   ON (reply:REPLY) ASSERT reply.ids IS UNIQUE

3. طلبات Cypher الخاصة بي وطلبات JSON

3.1. عندما يتطلب سجل واحد إنشاء عقدة واحدة ، يبدو وصف الوظيفة أدناه

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (child:Post {postId:1001, userId:901})"}}

3.2. عندما يتطلب سجل واحد إنشاء عقد واحد مع وجود علاقة واحدة ، يبدو أن الوصف الوظيفي يبدو أدناه

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (parent:Post {postId:1002, userId:902}) MERGE (child:Post {postId:1003, userId:903}) CREATE UNIQUE parent-[relationship:REPOST {ids:'1002_1003', created_at:'Wed Nov 06 14:06:56 AST 2013' }]->child"}}

3.3. عادةً ما أرسل 100 وصف وظيفي (مختلط 3.1 و 3.2) لكل دفعة تتطلب حوالي 150 ~ 250 مللي ثانية لإنجازها.

4. مشاكل الأداء

4.1. التزامن:

/db/data/batch (الهدف:/cypher) يبدو غير آمن مؤشر ترابط ، ويتم اختباره مع اثنين أو أكثر من مؤشرات الترابط المتزامنة مما أدى إلى انخفاض خادم Neo4J في الدقيقة الثانية.

4.2. الدمج مع القيود لا تعمل دائما.

عند إنشاء عقدين وعلاقة واحدة مع استعلام واحد (المذكور أعلاه في 3.2.) ، فإنه يعمل في وقت ما مثل السحر ؛ لكنه فشل في وقت ما مع cypherexecutionexception وقول أحد العقدة xxxx موجودة بالفعل مع التسمية AAAA والخاصية "bbbbb" = [CCCCC] ؛ من فهمي ، لا يفترض الاندماج إرجاع أي استثناء ، ولكن إرجاع العقدة إذا كانت موجودة بالفعل.

نتيجة للاستثناء ، ستفشل الدفعة بأكملها وتراجعها ، والتي تؤثر على معدل الإدراج الخاص بي.

لقد فتحت مشكلة في جيثب لهذه القضية ، https://github.com/neo4j/neo4j/issues/1428

4.3. إنشاء فريدة من نوعها مع قيود لا تعمل دائمًا لإنشاء العلاقة.

هذا مذكور في نفس قضية جيثب أيضا.

4.4. أداء:

في الواقع ، قبل استخدام الدُفعة مع Cypher ، جربت الفهرسة القديمة باستخدام get_or_create (/db/data/index/node/post؟ freadeness = get_or_create &/db/index/exper

نظرًا لطبيعة نقاط نهاية الفهرس القديمة هذه (يقومون بإرجاع موقع البيانات في الفهرس بدلاً من ذلك موقع البيانات في تخزين البيانات الفعلي) ، لذلك لم أتمكن )

أعلم أنه يمكنني تمكين Auto_indexing ، والتعامل مع تخزين البيانات مباشرة بدلاً من الفهرس القديم ، لكنهم ذكروا من 2.0.0 ، يوصى بفهرس المخطط على الفهرس القديم ، لذلك قررت التبديل إلى نهج فهرس Schema + Cypher +.

ومع ذلك ، مع Batch + Cypher ، لا يمكنني الحصول على حوالي 200 وصف وظيفي في الثانية الواحدة ، وكان من الممكن أن يكون أعلى بكثير إذا كان الدمج مع قيود يعمل دائمًا ، فلنقول حوالي 600 ~ 800/ثانية ، لكنه لا يزال أقل بكثير من 5 آلاف /س. لقد جربت أيضًا مؤشر المخطط دون أي قيود ، فقد انتهى الأمر بأداء أقل من حيث معدل الإدراج.

هل كانت مفيدة؟

المحلول

مع 2.0 ، أود استخدام نقطة النهاية المعاملة لإنشاء عباراتك على دفعات ، على سبيل المثال ، 100 أو 1000 لكل طلب HTTP وحوالي 30K-50K لكل معاملة (حتى تلتزم).

شاهد هذا للحصول على تنسيق نقطة نهاية المعاملات الجديدة:

http://docs.neo4j.org/chunked/milestone/rest-api-transactional.html

أيضًا لمثل هذا الأداء العالي ، نقطة نهاية الإدراج المستمر ، أوصي بشدة بكتابة امتداد الخادم الذي سيعمل ضد واجهة برمجة التطبيقات المدمجة ويمكنه بسهولة إدراج 10K أو أكثر من العقد وعلاقات في الثانية ، انظر هنا للوثائق:

http://docs.neo4j.org/chunked/milestone/server-unmanaged-extensions.html

للإدراج النقي ، لا تحتاج إلى Cypher. ولتوافق التزامن ، ما عليك سوى أخذ قفل في عقدة معروفة (لكل فرع فرعي تقوم بإدراجها) بحيث لا تكون الإدراج المتزامن مشكلة ، يمكنك القيام بذلك tx.acquireWriteLock() أو عن طريق إزالة خاصية غير موجودة من عقدة (REMOVE n.__lock__).

للحصول على مثال آخر لكتابة امتداد غير مُدار (ولكنه يستخدم Cypher) ، تحقق من هذا المشروع. حتى أنه يحتوي على وضع قد يساعدك (نشر ملفات CSV إلى نقطة نهاية الخادم ليتم تنفيذها باستخدام عبارة Cypher لكل صف).

https://github.com/jexp/cypher-rs

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top