مينا عادل
English احجز مكالمة
كل الأعمال إصلاح الأنظمة البطيئة

تقبّل الموظفون أن النظام بطيء. لم يكن كذلك — كان قابلًا للإصلاح.

شاشات كانت تستغرق نحو ثانية صارت تُفتح فورًا. صفحة كانت تتجمّد تسع ثوانٍ صارت تُحمَّل مباشرة. أُصلح على النظام الحيّ أثناء ساعات العمل.

القطاع
مجموعة تجزئة بعشرات الفروع
السنة
2026
بُني بـ
Odoo · PostgreSQL · Python

النتيجة

فتح شاشة التحويلات
قبل
نحو ثانية 910 ms
بعد
فوري < 50 ms
  • أكثر الشاشات استخدامًا تُفتح دون انتظار
  • صفحة كانت تتجمّد تسع ثوانٍ صارت تُحمَّل فورًا
  • طُبِّق على النظام الحيّ أثناء الدوام — دون إيقاف أحد عن العمل
  • يرى المستخدمون السجلّات نفسها بالصلاحيات نفسها تمامًا

الوضع

مجموعة تجزئة تُدير عشرات الفروع على نظام واحد. الجميع يعلم أن النظام بطيء، والجميع توقّف عن ذكر ذلك — فقد بنى الموظفون يومهم حول فترات الانتظار. بعض الشاشات كانت تستغرق نحو ثانية لتُفتح. وواحدة كانت تستغرق تسعًا.

حين تصل الأمور إلى هذا الحدّ، يكون الافتراض المعتاد أن النظام تجاوز قدرة الخادم، وأن الحلّ هو إنفاق المال على عتاد أكبر. وهو افتراض مكلف، وغالبًا خاطئ.

ما وجدته

قِستُ قبل أن أفترض. أبطأ العمليات في النظام أشارت إلى موضعين، ولم يكن أيٌّ منهما في العتاد — ولا في نظام أودو نفسه. كلاهما في كود مخصّص كُتب قبل سنوات، وكلاهما الخطأ ذاته.

كان النظام يطلب كل شيء من قاعدة البيانات، ويسحب النتيجة كاملة إلى الذاكرة، ثم يُصفّيها بعد ذلك للوصول إلى الصفوف القليلة الظاهرة على الشاشة. في إحدى الشاشات كان ذلك يعني نقل أكثر من ثمانين ألف سجلّ لعرض ثمانين منها. وفي أخرى، عدّاد يعمل مرة لكل صف حوَّل تحميل صفحة واحدة إلى مئة وستين رحلة منفصلة إلى قاعدة البيانات.

والنقطة المهمة: لم يكن أيٌّ من هذه الاستعلامات يبدو بطيئًا بمفرده. صارت مشكلة فقط حين حسبتُ عدد مرات تكرارها.

ما غيّرته

ثلاثة أمور، مرتّبة بحسب أثرها:

  1. دع قاعدة البيانات تُصفّي. بدل جلب كل شيء ثم تضييقه، صار الكود يطرح سؤالًا محدّدًا ويحصل على إجابة محدّدة، فيصل حدّ الصفوف الخاص بالشاشة إلى قاعدة البيانات أخيرًا.
  2. اسأل مرة واحدة، لا مرة لكل صف. صار العدّاد استعلامًا مجمَّعًا واحدًا للصفحة كلها.
  3. أضفتُ الفهارس الناقصة ليتمكّن النظام من الوصول إلى الصفوف مباشرة بدل قراءة جداول كاملة.

الخطأ نفسه كان موجودًا في ستة مواضع أخرى. أصلحتُها جميعًا، لا الموضعين المُبلَّغ عنهما فقط.

النتيجة

انتقلت شاشة التحويلات من نحو ثانية إلى أقل من خمسين جزءًا من الألف من الثانية. والصفحة التي كانت تتجمّد تسع ثوانٍ صارت تُحمَّل فورًا. وانخفض ضغط الذاكرة على الخادم، إذ لم يعد يحتفظ بعشرات الآلاف من السجلّات لكل مستخدم في كل تحميل.

لم يتغيّر شيء يراه المستخدم: السجلّات نفسها والصلاحيات نفسها قبل وبعد — فإصلاح أداءٍ يُغيّر بصمت ما يُسمح لشخص برؤيته ليس تحسينًا، بل حادثة أمنية.

طُبِّقت الفهارس على قاعدة بيانات الإنتاج الحيّة أثناء ساعات العمل دون قفل أي جدول، فلم يتوقّف نشاط الشركة لحظة.


للمهتمّين بالتفاصيل التقنية

السببان الجذريان: حقل بحث محسوب يُرجع معرّفات مُحلّلة في بايثون بدل إرجاع domain — ما منع تمرير LIMIT الخاص بالعرض إلى قاعدة البيانات — و N+1 كلاسيكي في عدّاد بلا @api.depends، بكلفة ١٦٠ مسحًا متتاليًا لكل عرض صفحة. الإصلاح: إرجاع domains من دوال search، واستبدال العدّاد بـ read_group واحد، وإضافة ثلاثة عشر فهرسًا عبر CREATE INDEX CONCURRENTLY لبنائها على قاعدة حيّة دون قفل. وسُمّيت الفهارس لتطابق ما يولّده الـ ORM، فتتعرّف عليها ترقيات الوحدات لاحقًا بدل إعادة بنائها.

أسماء العملاء والتفاصيل التعريفية محجوبة عمدًا. كل رقم في هذه الصفحة مأخوذ من نظام يمكنني فتحه.

بلا تكلفة وبلا عروض بيع

احجز مكالمة مجانية ٣٠ دقيقة

أحضِر المشكلة التي تؤجّلها باستمرار. سنحدّد معًا إن كان إصلاحها يستحق، وما الذي يتطلّبه، وهل أنا الشخص المناسب لها.

  • نظام بطيء ولا أحد يعرف السبب
  • ترقية متوقّفة في منتصف الطريق
  • مشروع على وشك البدء وتريد رأيًا ثانيًا
اختر وقتًا مباشرة إلى تقويمي. بلا نماذج تملؤها أولًا.
مينا عادل على مكتبه