المحــ البرمجى ــتوى
11-27-2006, 11:39 AM
عنوان الدرس: الفهارس في MySQL
قبل أن نتعلم كيفية إضافة و إزالة الفهارس سنتعرف أولا على الفهارس, إذن لنبدأ على بركة الله.
قد تتساءل ما الفائدة من الفهارس و ماذا تقدم لنا الفهارس؟
لنفرض أنك تبحث في قاموس عن كلمة ما و لنفرض أنها كلمة System فإنك ستفتح باب حرف الـ S ثم تتجاوز عدة صفحات حتى تصل إلى الحرف الثاني Y و كذلك الأمر بالنسبة إلى باقي الحروف, حسنا .. تصور أنك تبحث عن هذه الكلمة في قاموس عشوائي! إذن ستقوم بالبحث في كل صفحة و كل كلمة, و هذه هي الصورة بالنسبة للفهارس في قواعد البيانات, دعنا نأخذ المثال التالي, لنفرض أن لديك جدول مؤلف من عمودين الأول مفهرس و الثاني غير مفهرس كما يلي:
create table my_table(
col_1 varchar(15) not null primary key,
col_2 varchar(15) not null );
ثم قمت بإدخال 20000 صف في الجدول, ثم قمت بكتابة استعلامين متشابهين بالصياغة القواعدية كما يلي:
select * from my_table where col_1=3;
select * from my_table where col_2=3;
لا تهتم الآن بالاستعلامين لأننا سنتكلم عن الاستعلامات في MySQL لاحقا إن شاء الله.
في الاستعلام الأول سيستخدم MySQL فهرسا من أجل التعليمة where بينما في الاستعلام الثاني سيتم البحث في كل الصفوف لذلك فإن الاستعلام الأول أسرع بعدة مرات من الاستعلام الثاني على الرغم من أن كلاهما استعلامات سريعة لكن سيختلف الحال مع ملقم ويب نشط يقوم بمعالجة مئات الاستعلامات في الثانية أضف إلى ذلك ازدياد حجم الجداول و الاستعلامات, و هنا تبرز أهمية الفهرس.
و الصيغة القواعدية لإنشاء فهرس هي:
index index_name(indexed_col);
حيث أن indexed_col هو اسم العمود الذي تمت فهرسته, و من الممكن أن يمتد الفهرس على أكثر من عمود و الحد الأقصى هو 16 عمود, يتم إنشاء الفهرس على أكثر من عمود كما يلي:
index index_name(col_1,col_2, … ,col_16);
أما مبدأ عمل الفهرس فيمكنك أن تتخيل أن العمود المفهرس هو كخط مستقيم و يتم تخزين قيمة وسطية في الفهرس فإذا جاء استعلام يطلب قيمة أكبر من القيمة الوسطية فإن الفهرس يبحث باتجاه اليمين فرضا و إذا جاء استعلام يطلب قيمة أصغر القيمة الوسطية فسيبحث الفهرس باتجاه اليسار.
# أنواع الفهارس:
للفهارس ثلاث أنواع و هي:
1. primary key
:
حيث أن MySQL يقوم بفهرسة المفتاح الأساسي Primary Key لذلك فهو يعد نوع من أنواع الفهارس.
2. unique :
كلمة unique معناها وحيد أو فريد و هي في MySQL تدل فعلا على معناها, و عندما نصرح عن عمود أنه فريد فإننا نقصد بذلك أن القيم التي يتم إدخالها في هذا العمود هي قيما فريدة أي غير متكررة, و على سبيل المثال إذا كان لدينا عمود يحوي البريد الإلكتروني فمن المستحيل أن يكون هناك بريدين إلكترونيين متشابهين لذلك هذا العمود يضم قيما غير متكررة أي فريدة, أما إذا كان لدينا عمود يحوي أسماء فمن الممكن جدا أن تتكرر الأسماء و بالتالي فإن هذا العمود يضم قيما متكررة.
كيف أتمكن من إضافة عمود فريد unique : تتم لإضافته تماما مثل المفتاح الأساسي أي أنك تستطيع أن تضيفه كما لو أنه سمة كما في المثال التالي:
create table test(
col_1 varchar(10) not null unique);
أو بشكل منفصل كما يلي:
create table test(
col_1 varchar(10) not null,
unique index_name(indexed_col));
ما الفرق بين الطريقتين: في الطريقة الأولى هناك سيئتين الأولى أنك لن تستطيع أن تمد الفهرس على أكثر من عمود و الثانية أن هذا الفهرس سيكون بلا اسم (لكن MySQL يعطيه افتراضيا نفس اسم العمود الذي تمت فهرسته), وفي الطريقة الثانية هناك حسنتين الأولى أنك تستطيع أن تمد الفهرس على أكثر من عمود و الثانية أنك تستطيع وضع اسما لهذا الفهرس.
3. index :
ذكرنا في الدرس (بناء الجداول في MySQL - الجزء الأول) كيفية إنشاء الفهرس من النوع index .
و بذلك نكون قد أعطيناك بفضل من الله فكرة جيدة عن الفهارس.
تعرفنا على أنواع الفهارس الثلاث و هي Primary Key , Unique , Index و قد فصلنا أهم الفروق و المزايا لهم, و الآن سنكمل ما قلناه في الدرس السابق, لنبدأ على بركة الله.
قلنا في الدرس الماضي أنه من الممكن أن ننشىء فهرسا على أكثر من عمود, و أيضا من الممكن أن ننشىء فهرسا على جزء من عمود, أي أنه في حال كان لدينا عمودا نوعه varchar و قياسه 70 محرف أي varchar(70) , فيمكننا أن ننشىء فهرسا على أول 10 محارف فرضا, أو على أول 23 محرف, و ذلك حسب ما تريد.
حسننا لنأخذ هذا المثال التوضيحي:
بفرض أنه لدينا جدولا كما يلي:
create table my_table(
varchar_col varchar(120) not null,
text_col text not null,
index index_on_char_col(char_col(25)),
index index_on_text_col(text_col(200)));
بالنظر إلى هذا المثال ستلاحظ بأن الفهرس الأول لم يتم إنشاءه على كامل العمود بل على القسم الاستهلالي من العمود varchar_col.
و الفهرس الثاني تم إنشاءه فقط على أول 200 محرف من العمود text_col .
و الخلاصة أنه يمكن أن تنشىء فهرسا على القسم الاستهلالي من العمود الذي يكون نوعه char , varchar , و أيضا يمكنك إنشاء فهرسا على أول 255 محرف من الأعمدة ذات النوع text , tinytext , longtext , mediumtext
هنا تقريبا كون الصورة قد اكتملت عن الفهارس, و الآن سنضيف فهرس من النوع unique على العمود
ملاحظة:
قد تقول أخي القارىء لماذا لا أنشىء فهارس على جميع الأعمدة و تنتهي المشكلة. طبعا هذا الكلام غير مفيد, وذلك لأن الفهارس تستولي على جزء من مصادر النظام, وفي كل مرة يتم تشغيل أحد تعليمات update , insert سيتم تحديث الفهارس التي تم تطبيقها على هذا الجدول, فإذا كان الجدول مستخدما من أجل عمليات الإدراج فقط, فإن وجود الفهارس غير ضروري على ذاك الجدول لأنه سيسبب بطئاً في أداء MySQL و بالإضافة إلى أنها ستستحوذ على جزءا من ذاكرة الوصول العشوائي RAM .
و بذلك نكون قد أخذنا نظرة شبه كاملة عن الفهارس في MySQL
قبل أن نتعلم كيفية إضافة و إزالة الفهارس سنتعرف أولا على الفهارس, إذن لنبدأ على بركة الله.
قد تتساءل ما الفائدة من الفهارس و ماذا تقدم لنا الفهارس؟
لنفرض أنك تبحث في قاموس عن كلمة ما و لنفرض أنها كلمة System فإنك ستفتح باب حرف الـ S ثم تتجاوز عدة صفحات حتى تصل إلى الحرف الثاني Y و كذلك الأمر بالنسبة إلى باقي الحروف, حسنا .. تصور أنك تبحث عن هذه الكلمة في قاموس عشوائي! إذن ستقوم بالبحث في كل صفحة و كل كلمة, و هذه هي الصورة بالنسبة للفهارس في قواعد البيانات, دعنا نأخذ المثال التالي, لنفرض أن لديك جدول مؤلف من عمودين الأول مفهرس و الثاني غير مفهرس كما يلي:
create table my_table(
col_1 varchar(15) not null primary key,
col_2 varchar(15) not null );
ثم قمت بإدخال 20000 صف في الجدول, ثم قمت بكتابة استعلامين متشابهين بالصياغة القواعدية كما يلي:
select * from my_table where col_1=3;
select * from my_table where col_2=3;
لا تهتم الآن بالاستعلامين لأننا سنتكلم عن الاستعلامات في MySQL لاحقا إن شاء الله.
في الاستعلام الأول سيستخدم MySQL فهرسا من أجل التعليمة where بينما في الاستعلام الثاني سيتم البحث في كل الصفوف لذلك فإن الاستعلام الأول أسرع بعدة مرات من الاستعلام الثاني على الرغم من أن كلاهما استعلامات سريعة لكن سيختلف الحال مع ملقم ويب نشط يقوم بمعالجة مئات الاستعلامات في الثانية أضف إلى ذلك ازدياد حجم الجداول و الاستعلامات, و هنا تبرز أهمية الفهرس.
و الصيغة القواعدية لإنشاء فهرس هي:
index index_name(indexed_col);
حيث أن indexed_col هو اسم العمود الذي تمت فهرسته, و من الممكن أن يمتد الفهرس على أكثر من عمود و الحد الأقصى هو 16 عمود, يتم إنشاء الفهرس على أكثر من عمود كما يلي:
index index_name(col_1,col_2, … ,col_16);
أما مبدأ عمل الفهرس فيمكنك أن تتخيل أن العمود المفهرس هو كخط مستقيم و يتم تخزين قيمة وسطية في الفهرس فإذا جاء استعلام يطلب قيمة أكبر من القيمة الوسطية فإن الفهرس يبحث باتجاه اليمين فرضا و إذا جاء استعلام يطلب قيمة أصغر القيمة الوسطية فسيبحث الفهرس باتجاه اليسار.
# أنواع الفهارس:
للفهارس ثلاث أنواع و هي:
1. primary key
:
حيث أن MySQL يقوم بفهرسة المفتاح الأساسي Primary Key لذلك فهو يعد نوع من أنواع الفهارس.
2. unique :
كلمة unique معناها وحيد أو فريد و هي في MySQL تدل فعلا على معناها, و عندما نصرح عن عمود أنه فريد فإننا نقصد بذلك أن القيم التي يتم إدخالها في هذا العمود هي قيما فريدة أي غير متكررة, و على سبيل المثال إذا كان لدينا عمود يحوي البريد الإلكتروني فمن المستحيل أن يكون هناك بريدين إلكترونيين متشابهين لذلك هذا العمود يضم قيما غير متكررة أي فريدة, أما إذا كان لدينا عمود يحوي أسماء فمن الممكن جدا أن تتكرر الأسماء و بالتالي فإن هذا العمود يضم قيما متكررة.
كيف أتمكن من إضافة عمود فريد unique : تتم لإضافته تماما مثل المفتاح الأساسي أي أنك تستطيع أن تضيفه كما لو أنه سمة كما في المثال التالي:
create table test(
col_1 varchar(10) not null unique);
أو بشكل منفصل كما يلي:
create table test(
col_1 varchar(10) not null,
unique index_name(indexed_col));
ما الفرق بين الطريقتين: في الطريقة الأولى هناك سيئتين الأولى أنك لن تستطيع أن تمد الفهرس على أكثر من عمود و الثانية أن هذا الفهرس سيكون بلا اسم (لكن MySQL يعطيه افتراضيا نفس اسم العمود الذي تمت فهرسته), وفي الطريقة الثانية هناك حسنتين الأولى أنك تستطيع أن تمد الفهرس على أكثر من عمود و الثانية أنك تستطيع وضع اسما لهذا الفهرس.
3. index :
ذكرنا في الدرس (بناء الجداول في MySQL - الجزء الأول) كيفية إنشاء الفهرس من النوع index .
و بذلك نكون قد أعطيناك بفضل من الله فكرة جيدة عن الفهارس.
تعرفنا على أنواع الفهارس الثلاث و هي Primary Key , Unique , Index و قد فصلنا أهم الفروق و المزايا لهم, و الآن سنكمل ما قلناه في الدرس السابق, لنبدأ على بركة الله.
قلنا في الدرس الماضي أنه من الممكن أن ننشىء فهرسا على أكثر من عمود, و أيضا من الممكن أن ننشىء فهرسا على جزء من عمود, أي أنه في حال كان لدينا عمودا نوعه varchar و قياسه 70 محرف أي varchar(70) , فيمكننا أن ننشىء فهرسا على أول 10 محارف فرضا, أو على أول 23 محرف, و ذلك حسب ما تريد.
حسننا لنأخذ هذا المثال التوضيحي:
بفرض أنه لدينا جدولا كما يلي:
create table my_table(
varchar_col varchar(120) not null,
text_col text not null,
index index_on_char_col(char_col(25)),
index index_on_text_col(text_col(200)));
بالنظر إلى هذا المثال ستلاحظ بأن الفهرس الأول لم يتم إنشاءه على كامل العمود بل على القسم الاستهلالي من العمود varchar_col.
و الفهرس الثاني تم إنشاءه فقط على أول 200 محرف من العمود text_col .
و الخلاصة أنه يمكن أن تنشىء فهرسا على القسم الاستهلالي من العمود الذي يكون نوعه char , varchar , و أيضا يمكنك إنشاء فهرسا على أول 255 محرف من الأعمدة ذات النوع text , tinytext , longtext , mediumtext
هنا تقريبا كون الصورة قد اكتملت عن الفهارس, و الآن سنضيف فهرس من النوع unique على العمود
ملاحظة:
قد تقول أخي القارىء لماذا لا أنشىء فهارس على جميع الأعمدة و تنتهي المشكلة. طبعا هذا الكلام غير مفيد, وذلك لأن الفهارس تستولي على جزء من مصادر النظام, وفي كل مرة يتم تشغيل أحد تعليمات update , insert سيتم تحديث الفهارس التي تم تطبيقها على هذا الجدول, فإذا كان الجدول مستخدما من أجل عمليات الإدراج فقط, فإن وجود الفهارس غير ضروري على ذاك الجدول لأنه سيسبب بطئاً في أداء MySQL و بالإضافة إلى أنها ستستحوذ على جزءا من ذاكرة الوصول العشوائي RAM .
و بذلك نكون قد أخذنا نظرة شبه كاملة عن الفهارس في MySQL