صيد مشكلات N+1 والقضاء على الاستعلامات المهدرة في Laravel

غالبًا ما يكون العمل على تحسين الأداء مملًا.

الأمر لا يتعلق دائمًا بقصص البطولات حيث تقلل زمن الاستجابة بنسبة 80%. في معظم الأيام، يتعلق الأمر بالتنظيف. تجد استعلامات لم تكن تعلم أنك تقوم بتشغيلها، ثم تقوم بحذفها.

إذا كان تطبيق Laravel الخاص بك ينمو، فمن المرجح أنك تواجه هذه المشكلات الثلاث.

1. استعلامات N+1 المخفية

لا يمكنك إصلاح ما لا يمكنك رؤيته. استخدم أداة مثل beyondcode/laravel-query-detector في بيئة التطوير المحلية الخاصة بك. ستخبرك الأداة عندما تستخدم نمط "الحلقات والتحميل الكسول" (loop-and-lazy-load).

لا تقم بتشغيل هذه الأداة في بيئة الإنتاج (production)، لأنها تزيد من العبء على النظام. قم بتسجيلها فقط عندما يكون تطبيقك في وضع التطوير المحلي (local) أو وضع الاختبار (testing).

2. هدر التحميل المسبق (Eager Loading)

غالبًا ما يعالج المطورون مشكلات N+1 بإضافة with(). لكن هذا يخلق مشكلة جديدة؛ فقد تقوم بتحميل علاقة مسبقًا (eager-load) لم تعد الواجهة (view) تستخدمها.

إذا أدى إعادة التصميم إلى إزالة عمود من جدول ما، فيجب عليك إزالة استدعاء with() المقابل في المتحكم (controller). أنت تدفع ثمن بيانات تتخلص منها.

تعامل مع كل عملية تحميل مسبق كأنها "طلب" (claim). إذا كنت لا تستخدم البيانات، فقم بإلغاء هذا الطلب.

3. إعادة حساب نفس البيانات

تظل بعض القيم ثابتة طوال مدة الطلب (request). إذا قمت بحسابها عدة مرات، فأنت تهدر قدرة المعالج (CPU). استخدم تقنية الـ memoization لإصلاح ذلك.

مثال:

protected ?string $defaultConnection = null;

public function getDefaultConnectionName(): string
{
    return $this->defaultConnection ??= $this->resolveDefaultConnection();
}

المعامل ??= يقوم بحساب القيمة مرة واحدة ويعيد استخدامها لبقية الطلب.

4. فخاخ استعلامات لوحة التحكم (Dashboard)

غالبًا ما تقوم لوحات التحكم بتشغيل استعلام count() منفصل لكل بطاقة (card). إذا كان لديك ست بطاقات، فستقوم بتشغيل ستة استعلامات.

افعل هذين الأمرين بدلاً من ذلك:

  • قم بتجميع عمليات العد (counts): احصل على جميع الإجماليات لجدول واحد في استعلام واحد.
  • استخدم ذاكرة تخزين مؤقت (cache) قصيرة المدى: لا تحتاج إحصائيات لوحة التحكم إلى أن تكون محدثة لحظيًا بالثانية. قم بتخزينها مؤقتًا لمدة خمس دقائق.

سيدفع زائر واحد تكلفة الاستعلام، بينما يحصل الجميع الآخرون على النتيجة المخزنة مؤقتًا.

نصيحة أخيرة: منع التراجع (Regressions)

تفشل عمليات التنظيف إذا قام المطورون بإعادة إضافة الكود السيئ لاحقًا. استخدم Pest للتأكد من عدد الاستعلامات (assert). ضع سقفًا لعدد الاستعلامات التي يمكن أن تشغلها الصفحة. إذا أضاف مطور ما مشكلة N+1، فسيفشل الاختبار.

التحسين يتعلق في الغالب بالحذف. احذف عمليات التحميل غير المستخدمة. احذف القيم المعاد حسابها. احذف الاستعلامات غير الضرورية.

Source: https://dev.to/nasrulhazim/a-day-of-performance-hardening-hunting-n1s-and-killing-wasted-queries-in-laravel-568p