تحسين استعلامات Django ORM

يجعل Django ORM التعامل مع قواعد البيانات سهلاً، ولكنه يخفي خطراً ما. إذا قمت بجلب الكائنات المرتبطة بطريقة غير فعالة، فستتسبب في مشكلة استعلامات N+1.

هذا يعني أنك إذا جلبت 100 منشور، فقد يقوم تطبيقك بتشغيل 101 استعلام، مما يؤدي إلى إبطاء تطبيقك بشكل كبير.

استخدم هاتين الأداتين لإصلاح ذلك:

  1. select_related

استخدم هذه الأداة مع ForeignKey و OneToOneField.

فهي تستخدم SQL JOIN وتجلب البيانات المرتبطة في استعلام واحد.

  • مثال: المنشور لديه مؤلف واحد (Author).
  • الطريقة البدائية: 101 استعلام لـ 100 منشور.
  • الطريقة المحسنة: استعلام واحد باستخدام .select_related("author").
  1. prefetch_related

استخدم هذه الأداة مع ManyToManyField و reverse ForeignKeys.

فهي تقوم بتشغيل استعلامات منفصلة ثم تدمجها في Python.

  • مثال: المنشور لديه العديد من الوسوم (Tags).
  • الطريقة البدائية: استعلام واحد للمنشورات + استعلام واحد لكل وسم خاص بكل منشور.
  • الطريقة المحسنة: استعلامان إجمالاً باستخدام .prefetch_related("tags").

نصائح احترافية:

  • استخدم كائن Prefetch لتصفية البيانات المرتبطة قبل وصولها إلى حلقة التكرار (loop).
  • قم بربطهما معاً. يمكنك استخدام كليهما في queryset واحد لجلب المؤلفين والوسوم في آن واحد.
  • تجنب استدعاء .filter() على علاقة تم جلبها مسبقاً (prefetched) داخل حلقة التكرار؛ لأن ذلك يتجاوز التخزين المؤقت (cache) ويؤدي إلى الاتصال بقاعدة البيانات مرة أخرى.
  • استخدم .only() مع select_related لجلب الأعمدة التي تحتاجها فقط.

ملخص:

  • ForeignKey / OneToOne: استخدم select_related.
  • ManyToMany / Reverse FK: استخدم prefetch_related.

تحقق من عدد الاستعلامات باستخدام django-debug-toolbar لاكتشاف هذه المشكلات مبكراً.

المصدر: https://dev.to/fhva29/optimizing-django-orm-queries-a-practical-guide-to-selectrelated-and-prefetchrelated-1gpl