الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

دروس في تحسين الاستعلامات

بدأه DeaD SouL في 18 فبراير 2009 · 4 رد · 858 مشاهدة · في منتدى تطوير المواقع بـ PHP
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

اخواني الاعزاء..

اعتذر عن الغيبه عن المنتدى..

هذا الموضوع دعوة لتبادل الخبرات قبل ان يكون درس.. وذلك لتعم الفائده على الجميع

فياحبذا لو شاركنا الجميع بما يعلم

اليوم لكم في جعبتي موضوع مهم يهم جميع المبرمجين.. :D

كيف يمكننا ان نقلل من عدد الاستعلامات ؟

وكيف نستطيع تخفيف الضغط على القاعده ؟

فاذا ماعلمنا طريقة تقليل الاستعلامات سنخفف الضغط على القاعده بشكل كبير..

مع ذلك لن نكون قد حللنا المشكله جذريا.. ولكن نكون قد حسناها

اذا فإن مشكلة الضغط القاعده ينصب بشكل جوهري ورئيسي على عدد الاستعلامات..

مقدمه:

فمثلا: ان كتبنا صفحة معينة تعرض بيانات من القاعده.. ومجموع الاستعلامات كان تقريبا 15 استعلام

فاذا زار هذه الصفحه 100 شخص في نفس اللحظة فإن مجموع الاستعلامات سيكون (15 استعلام * 100 زائر) والمجموع 1500 استعلام

هل لك عزيزي القارئ ان تتخيل معنى 1500 استعلام؟ وما مدى الارهاق والضغط الذي تسببه الى القاعده.. لعرض نفس المحتوى لكل زائر؟

فهي ليست بالهينة بتاتا..

لذلك حسب وجه نظري المتواضعه.. أرى ان الحل يكمن في طريقتين.. لاغنى لأحدهما عن الأخرى

المرحلة الأولى:

هي معرفة وتطبيق الطريقة المثلى لعمل الاستعلامات (وتقليلها قدر الامكان وذلك بالبرط بين الجداول)

المرحلة الثانية:

هي باستخدام أصناف الذاكرة المؤقته لقاعدة البيانات - Database Caching Classes

فإذا طبقنا المرحلة الأولى فسنتمكن ان شاء الله من تقليل الاستعلامات في مثالنا السابق من 15 الى 3 استعلامات (وربما اكثر او اقل باستعلام او اثنين تقريبا)

فيكون المجموع بين300 الى 500 استعلام تقريبا بالمقارنة مع 1500 استعلام في مثالنا الاول.. فإنه انجاز جيد ولا بأس به اطلاقا..

ولكن مالحل اذا زاد عدد الزوار الى 500 ؟ فسيكون تقريبا 2000 استعلام (متوسط ال 3 استعلامات 5 استعلامات ، سنكون اكثر دقه بعد قليل بتطبيق المثال)

فمالحل اذا..؟

الحل هو في المرحلة الثانيه.. وهي باستخدام Database caching classes اما ان تقوم انت بكتابته او تستخدم احد الاصناف الجاهزة والتي موجوده بكثرة على النت

والسبب في ذلك اننا نقوم بتخزين البينات التي نقوم بجلبها بصورة متكررة من القاعده مع كل زيارة للصفحه وتخزينها في جدول مؤقت واحد. او نقوم بتخزينها في ملفات على الموقع قد تكون xml, txt, json الخ.. المهم انها تناسب مانريده

وبالتالي سترى ان عدد الاستعلامات يبقى ثابت ولا يتعدى الاستعلام او الاثنين مهما زاد عدد الزوار

لنتكلم عن المرحة الأولى:

وهي طريقة تقليل الاستعلامات عن طريق كتابتها بالطريقة الصحيحه للربط بين الجدوال.

الشق الأول:

المثال الذي سنطبق عليه الاستعلامات

بما ان البرمجة قريبه جدا من الرياضيات ان لم تكن هي كذلك بالفعل.. فافضل طريقه للشرح هي بتطبيق مثال

بفرض ان لدينا 3 جداول

الاول categories ويحتوي على

cat_id
cat_name
cat_total_books

والثاني books ويحتوي على

book_id
book_name
book_author_id
book_cat_id

والثالث authors ويحتوي على

author_id
author_name
author_total_books

ملاحظة: لاحظة اني اسبقت كل حقل باسم الجدول وذلك لكي يسهل علينا عملية التمييز بين اسماء الحقول في عملية الربط ، بالاضافة الى تعيين متغيرات متميزة عن الاخرى دون الحاجه لاستخدام خاصيه AS الموجوده في ال mysql (غالبا وليس دائما)

الشق الثاني:

طريقة جلب البيانات من القاعده وربط الجداول ببعضها البعض

الأن لنأتي لتطبيق المثال

نريد عمل صفحه لعرض اخر 10 كتب

فكيف يتم ذلك ؟؟

قد يقول شخص سهله.. وذلك بعمل استعلام اولي عن الكتب بالاستعلام التالي

SELECT book_id, book_name FROM books LIMIT 0,10

وعندما نقوم بفرز المصفوفه نعمل استعلامين اخرين عن الاول عن اسم الكاتب

SELECT cat_name FROM categories WHERE cat_id = $book_cat_id

بالفعل لقد استعطت اتمام المطلوب..

ولكن انتظر هل تعلم كم استعلام فعلت؟؟

الاستعلام الاساسي = 1

وفي كل عملية فرز ( ونحن مازلنا في التكرار) نقوم بعمل استعلامين اي استعلامين * الحد الاقصى للصفوف في الاستعلام الاساسي

اي 2 * 10 = 20 + الاستعلام الاساسي = 21 استعلام استعلام لكل زائر!!!!

أي بفرض ان لدينا 100 زائر فسيكون 21 استعلام * 100 زائر = 2100 استعلام!!!! إرهاق بمعنى الكلمة

حسنا يمكننا تنفيذها باستعلام واحد وهو الاستعلام الاساسي ونحن في عملية الفرز نقوم بتخزين معرفات الكتب في متغير واحد ونفصل بينهم بعلام الـ

,

ونفس الشيء بالنسبة لأسماء المؤلفين وبعد الانتهاء نقوم بعمل استعلامين الاول للكتب والثاني للمؤلفين وذلك باستخدام خاصية

WHERE cat_id IN ($all_cats)

هذا افضل بكثير.. حيث اننا عملنا المطلوب بـ 3 استعلامات...

أي 3 استعلامات * 100 زائر = 300 استعلام.. هممم!!

ولكن هل هناك طريقة افضل؟؟

قد يقول شخص نعم.. وذلك باستخدام اوامر ال JOIN وبذلك نستطيع عملها باستعلام واحد فقط...

ممتاز.. وهنا سنستخدم INNER JOIN لأنها اسرع من LEFT JOIN

تابع معي..

القاعده:

SELECT
	prefix_1.field_1 , 
	prefix_2.field_2 , 
	prefix_3.field_3 , 
	...
FROM
	table_1 prefix_1 ,
	table_2 prefix_2 ,
	table_3 prefix_3 ,
	...
WHERE
	prefix_1.field_1 = 'something' AND
	prefix_2.field_4 = prefix_3.field_5 OR
	...

حيث ان

prefix_X = اسم افتراضي نقوم نحن بتعيينه للتمييز بين الجداول التي نريد الاستعلام منها.. والاهي هو لاخبار خادم القاعده باننا نقصد الجدول الفلاني عن طريق هذا الاسم وذلك حينما نقوم بكتابة اسم الجدول بعد صيغة FROM

field_Y = اسم الحقل

table_Z = اسم الجدول

table_1 prefix_1 اخبرنا الخادم انن نقصد بالـ prefix_1 انه تابع للجدول table_1

وبتطبيق القاعده على فرضيتنا السابقه

SELECT
	bks.book_id , 
	bks.book_name , 
	cats.cat_name , 
	athrs.author_name
FROM
	books bks,
	categories cats,
	authors athrs
WHERE
	bks.book_author_id = athrs.author_id AND 
	bks.book_cat_id = cats.cat_id
LIMIT 0,10

bks.book_author_id = athrs.author_id

اشترطنا ان تكون قيمة معرف المؤلف الموجوده في جدول الكتب مساوية لقيمة قيمة معرف المؤلف الموجوده في جدول المؤلفين وذلك ليقوم بارجاع اسم المؤلف من جدول المؤلفين الذي سبق وحددناه عن طريق

athrs.author_name

bks.book_cat_id = cats.cat_id

بالضبط مثل السابق ولكن تتم المقارنه لـ قيمة معرف القسم وارجاع اسمه

وبذلك استطعنا جلب البيانات باستعلام واحد فقط

أي 1 استعلام * 100 زائر = 100 استعلام

نتيجه مرضيه جدا.. ولكننا سنواجه بعض المشاكل في حال ما اذا زاد عدد الزوار الى 1000 فسيكون عدد الاستعلامات 1000 استعلام.. وهذا ما سنقوم بمعالجته عن طريق ال Database Caching Classes وهي المرحة الثانيه ان شاء الله

الشق الثالث:

طريقة تحديث أكثر من جدول وأكثر من قيمة

الأن، نريد نقل الكتاب صاحب المعرف رقم 3

من القسم 4 الى القسم 5

ومن المؤلف 6 الى المؤلف 7

ويترتب على ذلك ان عدد الكتب الموجوده في القسم 4 قد نقصت كتاب

وزاد القسم 5 كتاب لذلك يجب تحديث العدادات الموجوده فيها وذلك بـ

طرح 1 من القسم 4

وزيادة 1 الى القسم 5

وكذلك هو الحال بالنسبة لجدول المؤلفين فقد نقص المؤلف 6 كتاب

وزاد المؤلف 7 كتاب لذلك علينا ايضا تحديث جدول المؤلفين بعمل التالي

طرح 1 من المؤلف 6

وزيادة 1 الى المؤلف 7

فتخيل ان عملت كل ذلك باستعلامات عاديه.. فكم عدد الاستعلامات؟

1 لتعديل القيم الموجوده في جدول الكتب

1 لانقاص 1 من جدول الاقسام

1 لزيادة 1 لجدول الاقسام

1 لانقاص واحد من جدول المؤلفين

1 لزيادة 1 لجدول المؤلفين

اي قمت بعمل 5 استعلامات.. بينما يمكنك الوصول لنفس النتيجه باستعلام واحد..

تابع معي من فضلك..

فبتطبيق القاعده التاليه

UPDATE 
	table_1 prefix_1, 
	table_2 prefix_2, 
	table_3 prefix_3, 
	...
SET 
	prefix_1.field_1 = 'YOUR_DATA' , 
	prefix_2.field_2 = 'YOUR_DATA' , 
	prefix_3.field_3 = 'YOUR_DATA' , 
	... 
WHERE 
	prefix_1.field_4 = 'SOMETHING' AND 
	prefix_2.field_5 = 'SOMETHING' AND 
	prefix_3.field_6 = 'SOMETHING' AND 
	...

يكون شكل الاستعلام كالتالي

UPDATE 
	categories cat_new, 
	categories cat_old, 
	authors auth_new, 
	authors auth_old, 
	books bks 
SET 
	bks.book_cat_id = 5 , 
	bks.book_author_id = 7 , 
	cat_new.cat_total_books = cat_new.cat_total_books+1 , 
	cat_old.cat_total_books = cat_old.cat_total_books-1 , 
	auth_new.author_total_books = auth_new.author_total_books+1 , 
	auth_old.author_total_books = auth_old.author_total_books-1 
WHERE 
	bks.book_id = 3 AND 
	cat_old.cat_id = 4 AND 
	cat_new.cat_id = 5 AND 
	auth_old.author_id = 6 AND 
	auth_new.author_id = 7

لاحظ

	categories cat_new, 
	categories cat_old,

اسمينا الاول بالجديد والثاني بالقديم وذلك لكي نتمكن من تحديث عداد القسم الجديد وعداد القسم القديم..

فالجديد هو الذي حصلت به زياده.. والقديم هو ما حصل به نقصان.. وبذلك نتمكن من زيادة وطرح مانريد بما اننا استطعنا فصلهم

فيكون:

	cat_new.cat_total_books = cat_new.cat_total_books+1 , 
	cat_old.cat_total_books = cat_old.cat_total_books-1 ,

مع انهم في الواقع نفس الحقل ولكن كيف سيعلم الخادم اننا نريد انقاص واحد من القسم 4 واضافة واحد الى القسم 5؟؟

ذلك يكون بالشرط الذي وضعناه

	cat_old.cat_id = 4 AND 
	cat_new.cat_id = 5 AND

فعمليتا التحديث + الشرط يكونان مبنيان على الاسم الذي سبق ووضعناه امام الجدول كما فعلنا هنا

اتمنى ان يكون الدرس قد افادكم قبل ان يعجبكم..

فإن كان كذلك.. فلا تبخلوا بدعوة صادقه لي ولأهلي بالتوفيق والمغفره

والدرس القادم ان شاء الله سيكون عن الشق الرابع وهو عمل احصائيات لعدة جداول وقيم باستعلام واحد

وبعد ذلك سأتطرق للمرحله الثانيه وهذا Database Caching

بالتوفيق

تم تعديل هذه المشاركة بواسطة DeaD SouL في 18 فبراير 2009 في 18:23

أعتذر وبشده عن انقطاعي.. وذلك بسبب مشروعي الجديد

-------------------

100(سبحان الله وبحمده، سبحان الله العظيم) = 0 سيئة

-------------------

dssighg7.png

#2

موضوع رائع جدا

لسا ماقرأته كامل بس كثير مفيد من البداية , المشكله وأنا بقرأ بالموضوع بفكر كيف رح أعيد شغل المواقع إلي عملتها بناء على هيك أفكار

بالتوفيق أخي بمشروعك :)

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

CMS Sfhati , Website Generator


نظام إدارة المحتوى صفحتي ... جربه الآن 


 


small-logo.png

#3

عزيزي bastr3

اسعدني مرورك..

وشكرا على الدعوة الجميله

كذلك اعتذر عن التأخير في الرد

واتمنى ان تكون قرأته بتمعن :)

بالتوفيق

أعتذر وبشده عن انقطاعي.. وذلك بسبب مشروعي الجديد

-------------------

100(سبحان الله وبحمده، سبحان الله العظيم) = 0 سيئة

-------------------

dssighg7.png

#4

نكمل اعزائي الشق الرابع

وهو عمل احصائيات سريعه

مازلنا في مثالنا السابق ونريد عمل احصائيات لـ مجموع الكتب المتاحه + عدد الاقسام + عدد المؤلفين + اخر كتاب تم اضافته مع بيان مؤلفه والقسم الذي ينتمي اليه

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

  1. $query = "
  2. SELECT DISTINCT
  3. cats.cat_name,
  4. bks.book_name,
  5. auth.author_name,
  6. (SELECT COUNT(*) FROM categories) AS total_categories,
  7. (SELECT COUNT(*) FROM books) AS total_books,
  8. (SELECT COUNT(*) FROM authors) AS total_authors
  9. FROM
  10. categories cats,
  11. books bks,
  12. authors auth
  13. WHERE
  14. cats.cat_id = bks.book_cat_id AND
  15. auth.author_id = bks.book_author_id
  16. ORDER BY bks.book_id DESC
  17. LIMIT 1
  18. "
  19.  
  20. $sql = @mysql_query($query);
  21. $statics = @mysql_fetch_array($sql);
  22.  
  23. echo "عدد الاقسام " . $statics['tot
    al_categories'] . "<br />";
  24. echo "عدد الكتب " . $statics['total_books'] . "
    <br />";
  25. echo "عدد المولفين " . $stati
    cs['total_authors'] . "<br />";
  26.  
  27. echo "اجدد كتاب تم إض
    1575;فته هو " . $statics['book_name'] . "في ا
    1604;قسم . $statics['cat_name'] . "&#1604;لمؤلف
    " . $statics['author_name'];
  28.  
  29.  

الجديد هنا هو

	(SELECT COUNT(*) FROM categories) AS total_categories,
	(SELECT COUNT(*) FROM books) AS total_books,
	(SELECT COUNT(*) FROM authors) AS total_authors

وهو اننا قمنا بعمل استعلام داخل الاستعلام الرئيسي على شكل انه قيمه حيث قمنا بتسميته باسم اخترناه مثل ال total_categories و total_books و total_authors

وهذا الاستعلام هو لحساب مجموع الصفوف

ولكن لاحظ اني استخدمت COUNT(*) عوضا عن COUNT(col_name)

والسبب ان ال COUNT(*) اسرع من الثانيه

وذلك لأن الاولى وهي COUNT(*) تقوم بقراءة المعلومات التي سبق ووضعها خادم القاعده على الجدول مثل عدد الصفوف

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

وبالمنطق فإن قراءة المعلومات ثم ارجاعها امر اسرع واخف ارهاقا وضغطا على خادم القاعده من عملية المسح وحساب عدد الصفوف صفا صفا..

اخيرا لاحظ

SELECT DISTINCT

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

انتهى..

اعتذر عن عدم شرحي للمرحلة الثانيه وهي database caching وذلك بسبب ضيق الوقت وبعض الانشغالات

بالتوفيق للجميع

تم تعديل هذه المشاركة بواسطة DeaD SouL في 22 فبراير 2009 في 12:54

أعتذر وبشده عن انقطاعي.. وذلك بسبب مشروعي الجديد

-------------------

100(سبحان الله وبحمده، سبحان الله العظيم) = 0 سيئة

-------------------

dssighg7.png

#5

صراحة افادني كثير هذا الدرس فقد قمت بالرجوع إلى صفحة في موقعي تقوم بعمليات تحديث بناء على ماقام به الزوار من تصويت وتعليق وغيرها فوجدت انني أقوم بكل عمليه منفصله عن الأخرى وعند تنفيذ هذه التحديثات يأخذ وقت طويل جدا إلى أن يعطى تايم أوت وبعد تطبيق الدرس على هذه الصفحة أصبح الوقت الذي تنفذ فيه الصفحة تقريبا عشرة ثوان و بعدد قليل جدا من الإستعلامات

وإلى الآن لم أقرأ الدرس كامل ... لآنني مشغول وعندما أتفرغ سأقوم بتطبيقه حرفيا

شكرا لك وجزاك الله خيرا

CMS Sfhati , Website Generator


نظام إدارة المحتوى صفحتي ... جربه الآن 


 


small-logo.png

مواضيع مشابهة