أفضل طرق تقليل عدد Queries في Laravel (بدون تعقيد)
في أحد المشاريع، كان عندي endpoint بسيط يعرض قائمة الطلبات… كل شيء كان يبدو طبيعي.
لكن بعد ما زاد عدد البيانات، صار الـ API بطيء بشكل واضح… رغم أن الكود “شكله صحيح”.
بعد تتبع المشكلة، اكتشفت أن السبب لم يكن في السيرفر… بل في عدد الاستعلامات.
Laravel يعطيك سهولة كبيرة في التعامل مع البيانات، لكن لو لم تنتبه، ممكن تنفذ مئات الاستعلامات بدون ما تشعر.
1. تحميل العلاقات بشكل صريح بدل الاعتماد على الوصول التلقائي
مثال بسيط:
$orders = Order::all();
foreach ($orders as $order) {
echo $order->customer->name;
}
هذا الكود يولد استعلام لكل عنصر داخل الحلقة.
الحل:
$orders = Order::with('customer')->get();
بهذا الشكل يتم تحميل البيانات المرتبطة في استعلام واحد.
2. اختيار الحقول المطلوبة فقط
كثير من الأحيان نرجع كل الأعمدة بدون حاجة:
User::all();
لكن غالبًا نحتاج فقط بعض الحقول.
الحل:
User::select('id', 'name')->get();
هذا يقلل حجم البيانات ويحسن الأداء.
3. تجنب استخدام all() في البيانات الكبيرة
استخدام all() مع جداول كبيرة يستهلك الذاكرة ويبطئ النظام:
Order::all();
الحل:
Order::latest()->paginate(20);
أو في حالات المعالجة:
Order::chunk(100, function ($orders) {
// processing
});
التعامل مع البيانات على دفعات أفضل بكثير.
4. استخدام withCount بدل جلب العلاقات
أحيانًا نحتاج فقط عدد العناصر:
$users = User::with('orders')->get();
foreach ($users as $user) {
echo $user->orders->count();
}
هذا يحمل كل البيانات فقط لحساب العدد.
الحل:
$users = User::withCount('orders')->get();
ويصبح:
$user->orders_count;
أسرع وأخف بكثير.
5. استخدام exists بدل count
إذا كنت تريد التحقق فقط:
if (User::where('email', $email)->count() > 0) {
// exists
}
الأفضل:
if (User::where('email', $email)->exists()) {
// exists
}
exists أسرع لأنه يتوقف عند أول نتيجة.
6. تجنب الحلقات التي تحتوي على Queries
من الأخطاء الشائعة:
foreach ($users as $user) {
$orders = Order::where('user_id', $user->id)->get();
}
هذا يعني Query لكل عنصر.
الحل:
$users = User::with('orders')->get();
أو استخدام whereIn عند الحاجة.
7. استخدام Cache في البيانات المتكررة
إذا كان نفس الاستعلام يتكرر:
$products = Product::all();
الحل:
$products = Cache::remember('products', 60, function () {
return Product::all();
});
تقليل الضغط على قاعدة البيانات بشكل واضح.
8. استخدام lazy loading عند الحاجة فقط
ليس كل علاقة تحتاج تحميل مباشر.
يمكنك تحميلها عند الحاجة:
$orders->load('customer');
هذا يعطيك مرونة أكبر.
9. استخدام Debug Tools لمراقبة الاستعلامات
أحيانًا المشكلة لا تكون واضحة.
استخدم أدوات مثل:
- Laravel Debugbar
- DB::listen()
DB::listen(function ($query) {
Log::info($query->sql);
});
رؤية الاستعلامات هي أول خطوة للتحسين.
تقليل عدد Queries لا يعني كتابة كود معقد… بل فهم كيف يتعامل Laravel مع البيانات.
- حمّل العلاقات بشكل صحيح
- لا ترجع بيانات لا تحتاجها
- استخدم pagination و chunk
- تجنب الاستعلامات داخل الحلقات
- راقب الأداء دائمًا
في كثير من الحالات، تقليل عدد الاستعلامات من 100 إلى 5 فقط يمكن أن يغيّر أداء النظام بالكامل.
المشكلة ليست في Laravel… بل في طريقة استخدامه.