NPlusone هي مكتبة للكشف عن مشكلة الاستعلامات N+1 في Python Orms ، بما في ذلك Sqlalchemy و PeeWee و Django Orm.
العديد من مكتبات تعيين الكائنات (ORM) الافتراضية للتحميل كسول للعلاقات. يمكن أن يكون هذا النمط فعالًا عندما يتم الوصول إلى الصفوف ذات الصلة نادراً ما يتم الوصول إليه ، ولكن يصبح بسرعة غير فعالة حيث يتم الوصول إلى العلاقات بشكل متكرر. في هذه الحالات ، يمكن أن يكون تحميل الصفوف ذات الصلة بفارغ الصبر باستخدام JOIN
أكثر أداءً. لسوء الحظ ، يمكن أن يكون فهم وقت استخدام الكسول مقابل التحميل المتحمس تحديًا: قد لا تلاحظ المشكلة حتى يتباطأ تطبيقك إلى الزحف.
nplusone
هو أداة تنميط ORM للمساعدة في تشخيص الأداء الضعيف وتحسينه بسبب التحميل الكسول غير المناسب. تراقب nplusone
تطبيقات باستخدام Django أو SqlalChemy ويرسل إشعارات عندما تنبعث أحمال كسول محتملة باهظة الثمن. يمكنه تحديد سمة العلاقة المخالفة وخطوط رمز محددة وراء المشكلة ، والتوصية بإصلاحات لتحسين الأداء.
يكتشف nplusone
أيضًا التحميل غير المناسب للتنقل من أجل Flask-Sqlalchemy و Django ORM ، مما ينبعث من التحذير عندما يتم تحميل البيانات ذات الصلة بفارغ الصبر ولكن لا يمكن الوصول إليها في الطلب الحالي.
PIP تثبيت -u nplusone
يدعم NPlusone Python> = 2.7 أو> = 3.3.
ملاحظة: يجب استخدام nplusone
فقط للتطوير ويجب عدم نشره في بيئات الإنتاج.
ملاحظة: يدعم nplusone
Django> = 1.8.
أضف nplusone
إلى INSTALLED_APPS
:
installed_apps = ( ... 'nplusone.ext.django' ، )
أضف NPlusOneMiddleware
:
الوسيطة = (( 'nplusone.ext.django.nplusonemiddleware "، ... )
تكوين إعدادات التسجيل اختياريا:
nplusone_logger = logging.getLogger ('nplusone') nplusone_log_level = logging.warn
تكوين معالجات التسجيل:
التسجيل = { 'الإصدار': 1 ، "معالجات": { 'وحدة التحكم': { 'class': 'logging.streamhandler' ، } ، } ، 'Loggers': { 'nplusone': { "معالجات": ["وحدة التحكم"] ، "المستوى": "تحذير" ، } ، } ، }
عندما يقوم تطبيقك بتحميل البيانات بتكاسل ، سوف ينبعث nplusone
رسالة سجل:
استعلام N+1 المحتمل المكتشف على `<model>. <field>` `
فكر في استخدام select_reled أو prefech_reled في هذه الحالة.
عندما يقوم تطبيقك بتحميل البيانات ذات الصلة بفارغ الصبر دون الوصول إليها ، سيقوم nplusone
بتسجيل تحذير:
تحميل حريص غير ضروري غير ضروري تم اكتشافه على `<model>. <field>` `
التفاف التطبيق مع NPlusOne
:
من قارورة استيراد Flask من nplusone.ext.flask_sqlalchemy استيراد nplusone التطبيق = قارورة (__ name__) nplusone (التطبيق)
تكوين إعدادات التسجيل اختياريا:
التطبيق = قارورة (__ name__) app.config ['nplusone_logger'] = logging.getLogger ('app.nplusone') app.config ['nplusone_log_level'] = logging.error nplusone (التطبيق)
عندما يقوم تطبيقك بتحميل البيانات بتكاسل ، سوف ينبعث nplusone
رسالة سجل:
استعلام N+1 المحتمل المكتشف على `<model>. <field>` `
فكر في استخدام subqueryload
أو joinedload
في هذه الحالة ؛ انظر دليل Sqlalchemy لتحميل العلاقة عن الوثائق الكاملة.
عندما يقوم تطبيقك بتحميل البيانات ذات الصلة بفارغ الصبر دون الوصول إليها ، سيقوم nplusone
بتسجيل تحذير:
تحميل حريص غير ضروري غير ضروري تم اكتشافه على `<model>. <field>` `
للحصول على أطر أخرى تتبع مواصفات WSGI ، لف التطبيق الخاص بك باستخدام NPlusOnemDdleware. يجب أيضًا استيراد ملحق nplusone
ذي الصلة لـ ORM:
زجاجة استيراد من nplusone.ext.wsgi استيراد nplusonemddleware استيراد nplusone.ext.sqlalchemy التطبيق = nplusonemiddleware (bottle.app ())
تقترن عمليات التكامل أعلاه بدورة الاستجابة للطلب. لاستخدام nplusone
خارج سياق طلب HTTP ، استخدم مدير سياق Profiler
: يجب عليك أيضًا استيراد ملحق nplusone
ذي الصلة لـ ORM:
من nplusone.core استيراد البروفيلر استيراد nplusone.ext.sqlalchemy مع profiler.profiler (): ...
بشكل افتراضي ، يقوم nplusone
بتسجيل جميع الاستعلامات غير الضرورية التي يحتمل أن تكون غير ضرورية باستخدام مسجل يسمى "Nplusone". عند تعيين خيار تكوين NPlusOne_raise ، سيقوم nplusone
أيضًا برفع NPlusOneError
. يمكن استخدام هذا لإجبار جميع الاختبارات الآلية التي تنطوي على استفسارات غير ضرورية للفشل.
# django config nplusone_raise = صحيح # flask config app.config ['nplusone_raise'] = true
يمكن أيضًا تحديد نوع الاستثناء ، إذا رغبت في ذلك ، باستخدام خيار NPLUSONE_ERROR
.
لتجاهل الإخطارات من nplusone
على مستوى العالم ، قم بتكوين القائمة البيضاء باستخدام خيار nplusone_whitelist:
# django config nplusone_whitelist = [ {'label': 'n_plus_one' ، 'model': 'myapp.mymodel'} ] # flask-sqlalchemy config app.config ['nplusone_whitelist'] = [ {'label': 'unused_eager_load' ، 'model': 'mymodel' ، 'field': 'my_field'} ]
يمكنك النماذج ذات القائمة البيضاء بالاسم الدقيق أو عن طريق أنماط FNMatch:
# django config nplusone_whitelist = [ {'model': 'myapp.*'} ]
لقمع الإخطارات محليًا ، استخدم مدير السياق ignore
:
من إشارات الاستيراد nplusone.core مع signals.ignore (signals.lazy_load): # صفوف lazy-load # ...
معهد ماساتشوستس للتكنولوجيا مرخصة. راجع ملف الترخيص المجمعة لمزيد من التفاصيل.