الكثير من البرامج التي تعتمد على MySql تستخدم طرق متعددة لاجراء البحث في قواعد البينات بشكل سريع والحد من درجة الخطورة في الاستعلامات المعقدة
ولقد أجريت دراسة في هذا الموضوع لجميع الطرق والحلول التي تستخدم للبحث في قواعد البينات MySql
وايضا تسريع الاستعلام بواسطة الفهارس
فتفضل بالاطلاع على الموضوع الشيق والجدير بالاهتمام
الفهارس
يعتبر الفهرس index في MySql افضل الخصائص التي تساعد في سرعة الحصول على البينات المطلوبة .
يعتبر الفهرس فريد اذا كانت كل قيمة فيه تختلف عن غيرها مثل مفاتيح الجداول PRIMARY KEY يعتبر فهرس فريد وهو اسرع الطرق للاستعلام
اما الفهارس غير الفريدة قابلة لتطبيق بناء على البينات الموجودة بها وهذا النوع من الفهارس نجرية على الحقول التي نجري عليها استعلام البحث بستخدام الكلمة الاساسية like
اذا الفهارس تفيد تسريع الاستعلام بصورة عامة
التطبيق
على أفتراض ان لدينا جدول يحفظ فيه الكثير من النصوص ونريد ان نبحث عن كلمة في الحقل الخاص بنص هنا من الافضل ان يكون الحقل مفهرس وبنسبة لنصوص يتم فهرسة كامل النص
مثال :
جدول المقالات لبرنامجنا يفترض ان يتم انشائة بطريقة التالية
كود:
CREATE TABLE articles (
id mediumint(9) default NULL auto_increment,
title varchar(80) NOT NULL default '',
writer varchar(65) NOT NULL default '',
text mediumtext NOT NULL,
date int(11) NOT NULL default '0',
stat int(1) NOT NULL default '0',
reader int(10) NOT NULL default '0',
PRIMARY KEY (id),
KEY date_reader(date,reader),
FULLTEXT KEY text(text)
);
هذا الجدول يحتوي على
الحقل id ويعتبر PRIMARY KEY كما قمنا بتعريفة في السطر رقم 9
وهو المفتاح الرئيسي للجدول ويعتبر فهرس فريد
السطر رقم 10
KEY date_reader(date,reader),
قمنا بانشاء فهرس لحقلين الحقل الاول هو حقل التاريخ والحقل الثاني هو حقل عدد زوار المقال
لماذا تم انشاء فهرس لهذه الحقول
نحتاج في برنامج المقالات ان نعرض المقالات المضافة قبل شهر
فنجري حسابات نستنتج منها التاريخ قبل شهر ونحفظة في متغير
lastmonth بعد ذلك نجري الاستعلام بناء على التاريخ
ويتم الاستعلام بهذا الشكل
كود:
SELECT * FROM articles WHERE date >='$lastmonth'
وبناء على هذا المثال يتم انشاء فهرس لكل حقل نستعين به في الاستعلام بعد الشرط WHERE
كم الوقت المتوقع اختزالة من هذه العملية ؟
لو اجري هذا الاستعلام على مليون حقل ربما يستغرق 60 ثانية اذا لم يكن هناك فهارس اما مع وجود فهرس يختزل وقت الاستعلام السابق
ليصبح 0.08 ثانية فقط :SMI:
ولكن ماذا لو استخدمنا البحث بصيغة التشابة like هنا الوقت المستنفذ في البحث كبير وربما يشكل خطورة على قاعدة البينات
لدينا في الجدول articles حقل text هذا الحقل يحفظ فيه كتلة كبيرة من النصوص وفي حالة البحث عن كلمة في الحقل text بستخدام like على افتراض وجود مليون حقل ونتوقع تكرار الكلمة اكثر من الف مرة في هذه الحقول , اتوقع ان هذا البحث قد يدمر القاعدة برمتها .
لذلك نضع جميع الاحتياطات الممكنة لتفادي هذه المشكلة
اولا : نجري فهرس للحقل text كما تلاحظ في الجدول السابق في السطر الاخير FULLTEXT KEY text(text)
ثانيا : يمنع البحث عن الكلمات التي تستخدم بستمرار في النصوص ولا يفترض ان يتم البحث عنها مثل ( حروف الجر , أن واخواتها .... الخ )
ولكي لا نستغرق الوقت في حصر هذه الكلمات نضع حد لعدد احرف كلمة البحث والحد المناسب اكثر من ثلاثة احرف
ومع ان هذا الحد قد يدخل فيه بعض الكلمات المتوقع البحث عنها مثلا على المستوى العربي مثلا ( قطر )
ولكن بنسبة لي افضل التضحية بالكثير من الكلمات حتى احافظ على سرعة البحث والحد من خطر هذا البحث
ثالثا : يمنع البحث عن رموز مثل الاقواس والنجمة * وغيرها من الرموز
الان وقد تم ضبط البحث ولكن تظهر لنا مشكلة لم تكن في الحسبان
وهي عرض النتائج
جدول نتائج البحث
المشكلة لو ان عدد النتائج كبير هل نقوم بعرض جزء منها وفي الصفحة التالية نقوم بعملية البحث من جديد ونعرض جزء غير السابق ؟
هذا غير مجدي مع ان العملية ناجحة ولكن البحث بهذه الطريقة يعتبر اجهاد لقاعدة البينات
لهذا يتم انشاء جدول خاص بنتائج البحث search_results
ولهذا الجدول خصائص اتفق عليها المبرمجين وخصائص تضاف بناء على بنية البرنامج او الجدول الذي نبحث فيه
بنسبة لجدول المقالات السابق
نضع جدول جديد لنتائج البحث search_results
كود:
CREATE TABLE search_results (
id mediumint(9) default NULL auto_increment,
articl_id text NOT NULL,
articl_word varchar(100) default NULL,
search_date int(11) NOT NULL default '0',
articl_date int(11) NOT NULL default '0',
articl_order varchar(4) NOT NULL default 'desc',
articl_max int(10) NOT NULL default '0',
user_id mediumint(10) default '0',
ip varchar(64) default NULL,
PRIMARY KEY (id)
);
الفائدة من الجدول السابق
1) عرض النتائج على صفحات متعددة وتنسيق العرض
2) حفظ الكلمة التي تم البحث عنها بذلك نستطيع العودة لهذه النتيجة اذا كا تخزين النتائج غير مؤقت في هذا الجدول
3 ) حفظ رقم الايبي لمن قام بالبحث وحفظ الاسم اذا كان احد الاعضاء لمعرفة ما اذا كان القصد من البحث الضرر ويتم ايقاف صاحب رقم الايبي عن البحث ومن الافضل وضع حد معين لرقم الايبي مثلا يحق له استخدام محرك البحث في الساعة خمس مرات ( مجرد اقتراح )
تعال نلقي نظرة على الحقول الخاصة بالجدول السابق
الحقل articl_id يحفظ فيه ارقام المقالات التي يوجد بها كلمة شبية كلمة البحث وتفصل هذه الارقام اما بفاصة , او برمز يستخدمة المبرمج لان هذا الرمز او الفاصلة سوف تفرز النتائج على اساسها
الحقل articl_word نحفظ فيها كلمة البحث بغية الرجوع اليها اذا تكرر البحث عنها
search_date تاريخ البحث ويفيد التاريخ في حذف الحقول اذا كان التخزين مؤقت او استخراج نتائج جديدة للمشاركات التي اضيفت بعد هذا التاريخ اذا كان التخزين دائم
الحقل articl_date والحقل articl_order
للبحث المتقدم اذا اختراح الباحث تاريخ معين للبحث بواسطة وا الثاني طريقة العرض من الاقدم للاحدث
والحقل articl_max هو عدد المواضيع التي وجد بها كلمة مشابة لكلمة البحث
أنشاء فهارس خاصة
من الطرق الاضافية لمعالجة البحث هي تخزين الكلمات المكتوبة في المقال كل واحدة على حدى بدون تكرار نفس الكلمة في نفس المقال
وتحفظ داخل جدول جديد search_words
كود:
CREATE TABLE search_words (
postid int(12) unsigned NOT NULL default '0',
word varchar(50) NOT NULL default '',
KEY word(word)
);
الفائدة :
في حالة البحث يتم البحث في الجدول search_words
في الحقل word وتعرض النتائج بناء على postid وهذه الطريقة استخدمتها في برنامج الداعية الالكتروني بالاضافة الى حقل جديد
هو cat int(10) NOT NULL default '0',
هذا الحقل يحدد اذا القسم الذي توجد به المشاركة هل هي في المقالات او القصص او الفتاوي وتم تطبيقة على سته اقسام تقريبا
جرب البحث في موقع الاسلام للجميع
http://www.alislam4all.com
وبحث عن كلمة رسالة
ومع ان البرنامج كتب باحدث الاساليب الى انه لازال ينقصة بعض التطوير الذي اتمنى ان اقوم به مستقبلا ان شاء الله
ومع اني اخترت هذا الاسلوب ولكن الافضل هو انشاء فهارس للحقول داخل الجداول كما في جدول المقالات السابق ولكن في الداعية الالكتروني استفيد بان البحث يتم في كل الاقسام وهذا ما تفتقر له مجلة المبرمج العربي وجميع المجلات التي نجهل الكثير من خطورت نصوصها البرمجية
نعود لجدولنا search_words يعتبر فهرس قمنا بانشائه ونتولى معالجة البحث فيه وهذا الجدول لا يستغني عن الجدول search_results اذا اردنا ان نتقن العمل ويكون البرنامج قادر على استيعاب الكثير من النصوص
تخزين الكلمات داخل الجدول search_words
يجب ان نضع ضوابط لحفظ الكلمات المدخلة في هذا الجدول
اولا : يمنع حفظ الكلمات التي تستخدم بستمرار في النصوص ولا يفترض ان يتم البحث عنها مثل ( حروف الجر , أن واخواتها .... الخ )
ثانيا : عدم حفظ الكلمة اكثر من مرة اذا تكررت في نفس النص
ثالثا : عدم حفظ وسوم html او اي اختصارات خاصة ببرنامجك مثل الابتسامات ...... الخ
رابعا : تحفظ الكلمات والرقم الخاص بالمشاركة التي توجد بها الكلم حتى نصل لها بشكل سريع
خامسا : لا تحفظ الا كلمات تتكون من حروف او ارقام وحروف معدى ذلك يتم استبعادة
جميع هذه الشروط قمت بكتابتها داخل دالة لبرنامج الداعية الالكتروني
وهي
كود PHP:
function search_words($postid,$post,$cat)
{
global $db;
$post = strip_tags($post);
$post = preg_replace('/\s/', ' ', $post);
$post = preg_replace('/[^a-z0-9أ-ي\-_ ]/', ' ', $post);
$post = preg_replace('/\s{2,}/', ' ', $post);
$post = trim($post);
$words = explode(' ', $post);
$words = array_unique($words);
foreach($words as $word)
{
if( strlen ($word) > 3 )
$db->query("INSERT INTO searchwords (postid, word, cat)
VALUES
($postid, '$word','$cat')");
}
}
مع العلم ان الجدول يحتوي على حقل اضافي لتحديد القسم
واعود واكرر ان الطريقة المثالية هي انشاء فهارس داخل نفس الجداول كما تم على جدول المقالات السابق articles
الطريقة المثالية لاجراء استعلام وبحث سريع في MySql
دراسة وتحليل : رفيع العتيبي
المصدر
http://www.rafiaphp.com/news.php?action=view&id=74
-------------