مقدمة

هذه المقالة موجهة لمطوري قواعد البيانات Database Developers بشكل عام ومطوري قواعد البيانات في مشروع أروى ARWA بشكل خاص.

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

 الحلول المقترحة

إن الحلول المقترحة لحل المسألة تنوعت في أفكارها ونتائجها، وهو ما أغنى المسألة وأوجد مجالاً للنقاش والتعلم، وهو الهدف الأساسي لهذه المقالات.

عدد الحلول المقترحة هو 10 حلول (8 حلول مرسلة مع حلين مقترحين من قبلي)وهي (مرتبة حسب تاريخ الإرسال):

دراسة الحلول المقبولة

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

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

ملاحظة:لم تأخذ أغلبية الحلول (باستثناء حل السيد أحمد غانم رقم 1) بعين الاعتبار أن القيود التي تم ترحيلها (IsPosted <> 0) هي فقط القيود التي تدخل في حساب المدين والدائن، وبالرغم من تأثير هذا الشرط على الأداء (يتطلب دمج Join مع الجدول ce000) فإن الحلول التي لم تحققه تم اعتبارها مقبولة كما هي.

تم دراسة الحلول المقبولة على جهازين مختلفين وباستخدام قاعدتي بيانات مختلفتين.

الجهاز الأول هو جهاز عادي بمواصفات متوسطة، أما الجهاز الثاني فهو مخدم بمواصفات جيدة.

قاعدة البيانات الأولى هي قاعدة بيانات متوسطة الحجم، أما قاعدة البيانات الثانية فهي قاعدة بيانات جيدة الحجم.

سيتم عرض النتائج على أربع جداول كل جدول يمثل حالة دراسة، ووفق المعايير التالية:

  1. الزمن الكلي الذي استغرقه تنفيذ الاستعلام بالميلي ثانية.
  2. زمن المعالجات CPU Time الذي استغرقه تنفيذ الاستعلام بالميلي ثانية، وقد يكون في بعض الأحيان أكبرمن الزمن الكلي وذلك نتيجة لأن خطة التنفيذ Execution Plan المستخدمة هي خطة تنفيذ تفرعية.
  3. عدد القراءات المنطقية Logical Reads التي تطلبها تنفيذ الاستعلام، وهي تمثل عدد القراءات من الذاكرة المخبئية Cache و لا يدخل ضمنها القراءات من الملفات الفيزيائية، هي تعد من أهم المعايير لدراسة أداء الاستعلامات، ولكنها ليست كافية لوحدها.
  4. عدد الكتابات Writes التي تطلبها تنفيذ الاستعلام، وهي تتضمن الكتابة على TempDB نتيجة استخدام جداول مؤقتة أو نتيجة خطة التنفيذ التي تشير إلى تخزين النتائج المؤقتة لتحسين أداء الاستعلامات.

ملاحظة:سترتب النتائج وفق معيار الزمن الكلي.

النتائج

جهاز عادي وقاعدة بيانات متوسطة الحجم

الترتيب الحل المقترح الزمن الكلي زمن المعالجات عدد القراءات المنطقية عدد الكتابات
1 محمد الباشا 455 656 51581 90
2 محمد الباشا2 2765 2766 258062 37
3 معاوية الرفاعي 3656 3641 403184 14
4 وسيم العش2 3812 3782 552288 25
5 أحمد غانم2 10640 10625 511814 55
6 وسيم العش1 13229 13141 691864 37
7 أحمد غانم1 21772 21688 955032 61
8 رضوان نصري 22591 21828 3167064 100
9 محمد القجة 175715 173782 173782 231

جهاز عادي وقاعدة بيانات جيدة الحجم

الترتيب الحل المقترح الزمن الكلي زمن المعالجات عدد القراءات المنطقية عدد الكتابات
1 محمد الباشا 19750 21141 467288 146
2 محمد الباشا2 24921 19969 687798 55
3 وسيم العش2 52921 47718 8687475 55
4 أحمد غانم2 142612 131422 10315913 61
5 رضوان نصري 160318 152437 13706039 291
6 وسيم العش1 172470 159953 12810629 392
7 معاوية الرفاعي 259546 255641 19103395 60
8 محمد القجة 401970 387609 11264301 672
9 أحمد غانم1 413724 413047 30062186 380

جهاز جيد وقاعدة بيانات متوسطة الحجم

الترتيب الحل المقترح الزمن الكلي زمن المعالجات عدد القراءات المنطقية عدد الكتابات
1 محمد الباشا 296 500 51205 98
2 محمد الباشا2 1890 1859 257820 44
3 وسيم العش2 2473 2437 551978 60
4 معاوية الرفاعي 2561 2500 402876 44
5 أحمد غانم2 2778 2734 511446 60
6 وسيم العش1 3424 3343 691239 88
7 أحمد غانم1 5446 5297 954377 88
8 رضوان نصري 7778 7688 3165891 104
9 محمد القجة 32843 32469 4146255 306

جهاز جيد وقاعدة بيانات جيدة الحجم

الترتيب الحل المقترح الزمن الكلي زمن المعالجات عدد القراءات المنطقية عدد الكتابات
1 محمد الباشا 7132 12969 436137 131
2 محمد الباشا2 11967 10969 684210 155
3 وسيم العش2 23224 23031 8682505 47
4 أحمد غانم2 33079 29594 10311155 52
5 وسيم العش1 40690 35594 12806518 83
6 رضوان نصري 46301 41875 13726787 142
7 معاوية الرفاعي 70514 70125 19098823 54
8 أحمد غانم1 98805 97937 30062481 89
9 محمد القجة 105268 104422 11253183 662

 

مناقشة النتائج

نلاحظ من قراءة النتائج أن لعدد القراءات المنطقية تأثيراً واضحاً على أداء الاستعلام، ولكنه وحده ليس كافياً فهنالك عوامل أخرى تؤثر أيضاُ ومنها القراءات الفيزيائية من الملفات.

كما أننا نلاحظ أثر استخدام التابع fnCurrency_fix وهو تابع إحادي القيمة Scalar Value Function على الأداء عند ازدياد حجم البيانات، ولتوضيح ذلك لنقارن أداء حل السيد معاوية الرفاعي وحل السيد وسيم العش رقم 2 (الذي يستخدم تابع جدولي القيمة Table Value Function)، فالأول كان أسرع عندما كان حجم قاعدة البيانات متوسطاً وكان الحاسب المستخدم حاسب عادي، بينما كان حل السيد وسيم العش رقم 2 أسرع في باقي الحالات. وطبعاً تمايزت الحلول المقترحة والتي تستخدم التابع fnCurrency_fix في أدائها وذلك تبعاً للموقع الذي تم استخدام هذا التابع فيه مما منحها خصائص متمايزة.

أما في ما يخص حل السيد أحمد غانم رقم 1 فهو الحل الأبسط والمباشر لهذه المسألة ولكنه من أبطأ الحلول لأنه أضاف طبقة أخرى من التوابع أحادية القيمة فوق باقي الحلول فهو يستخدم التابعين أحادي القيمة fnAccount_getCredit وfnAccount_getDebit اللذان يستخدمان التابع fnCurrency_fix بدورهما، لكنه الحل الوحيد (باستثناء الحلين المقترحين من قبلي) الذي أخذ بالاعتبار القيود المرحلة فقط.

أما في ما يخص الحلول المقترحة من قبل السادة رضوان نصري وأحمد غانم (الحل رقم2) ووسيم العش ومعاوية الرفاعي فهي تتشارك منهجية حل مشتركة (مقترحة أساساً من قبل السيد رضوان نصري) وهي تبين منهجية تفكير موجهة باستخدام التوابع جدولية القيمة بدلاُ ن التوابع أحادية القيمة، وهي منهجية سليمة ولها أثرها الواضح على الأداء من حيث التعامل مع البيانات كمجموعات وليس كأسطر مفردة، ومن حيث تكامل أجزاء الاستعلام مع بعضعا كوحدة واحدة يمكن أمثلتها من قبل محرك قواعد البيانات، ولكن جزئية استبدال التابع fnCurrency_fix بتابع آخر هي فكرة مميزة طرحها السيد وسيم العش في حله رقم 2 وكان لها الأثر الكبير على الأداء نتيجة ارتباط هذا التابع بجدول القيود وهو الجدول الأكبر بين كل الجداول المستخدمة في الاستعلام، ولكن آلية كتابة هذا التابع و كيفية استخدامه تحتاج لبعض التصحيح والأمثلة.

أما  في ما يخص حل السيد محمد القجة فهو ذو فكرة مميزة (سنناقشه في الفقة اللاحقة) ولكن أداءه منخفص نتيجة المنجية الإجراءاتية (لم أجد كلمة أفضل) بدلاً من الاستفادة من المزايا الموجودة في SQL Server، بالإضافة لآلية كتابة الاستعلامات التي يمكن أن تكتب بشكل أكثر أمثلةً.

أما في ما يخص حلولي للمسألة فإنها قائمة على شيء مشابه للأفكار المقترحة من قبل الآخرين، ولتكون كمثال عملي لما أشرت إليه في هذه الفقرة.

عرض للأفكار المقترحة

سأعدد الأفكار المقترحة من قبل المشاركين في حل المسألة وهي:

  • استخدام التوابع جدولية القيمة ودمجها ضمن الاستعلام كبنية واحدة، وقد تم اقتراحها أساساً من قبل السيد رضوان نصري.
  • استبدال التابع fnCurrency_fix أحادي القيمة بتابع آخر جدولي القيمة، وقد تم اقتراحها أساساً من قبل السيد وسيم العش.
  • استبدال التابع fnGetAccountsList بتابع أو استعلام آخر، وقد تم اقتراحها أساساً من قبل السيد وسيم العش ولكنه لم يقدم حلاً صحيحاً، ولكن حلي رقم 1 يستبدل هذا التابع باستعلام مستخدماً الـ CTE.
  • معالجة شجرة الحساب من الأوراق صعوداً، وقد تم اقتراحها أساساً من قبل السيد محمد القجة، وهي مشابهة للآلية المستخدمة في حلي رقم 1 ولكن مع الفرق بأني ولدت أسلاف الحسابات انطلاقاً من كامل جدول الحسابات ولم أحسبها من أجل كل حساب على حدا.
  • تجميع ارصدة الحسابات جمعاً جبرياً وهو الحل المقترح من قبل السيد هاني السائح والذي إن اكتمل بشكل صحيح قد يعطينا وجهة نظر مختلفة لحل المسألة.

الخاتمة

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