Professional Documents
Culture Documents
NET DataTables
تتوفر عدة استراتٌجٌات لتطوٌر قواعد البٌانات فً بٌئة تطوٌر الدوت نٌت فرٌموورك مثل ADO.NET Entity
Frameworkو ASP.NET Dynamic Dataو XMLو Hibernateو Linq to Sqlو ObjectDataSource
وغٌرها ومع ذلك ستجد فً كثٌر من الحاالت أن جداول ado .netما زالت قٌد االستخدام ربما ٌكون هذا بسبب أن
المعمارٌة الحالٌة تعتمد على جداول البٌانات أو لسهولة استخدامها فربما ٌتطلب العمل البقاء على الدوت نٌت 1وربما لم
ٌتوفر لدٌك الوقت لتصفح الطرق األخرى للوصول إلى البٌانات ومهما كان السبب فمن المفٌد أن نتعلم كٌفٌة زٌادة اداء
جدول البٌانات للحد األقصى وسوف نبحث فً اثنٌن من السٌنارٌوهات الشائعة :االستعالم عن البٌانات وتجمٌع البٌانات
االستعالم عن البيانات
قبل أن نناقش كٌفٌة التعامل مع البٌانات فً الذاكرة والمعاٌٌر المرتبطة بها دعنً أوضح انه فً معظم الحاالت ٌبدو
منطقٌا تجمٌع البٌانات أو االستعالم عنها فً قاعدة البٌانات .وهناك عدة أسباب لهذا فالسبب األول هو كون محرك قاعدة
البٌانات معاٌر بشكل جٌد من أجل القٌام بهذه العملٌات وسنرى بعد قلٌل أن جداول بٌانات ado .netلٌست بهذه الكفاءة
والسبب الثانً هو أنك كلما نقلت كمٌة بٌانات أقل عبر السلك ستحصل على أداء أفضل لعملٌات قواعد البٌانات وهذا ٌعنً
انك بحاجة لنقل النتائج فقط ولٌس البٌانات الخام والثالث إذا كنت تقوم بخزن كمٌات كبٌرة من البٌانات على اآللة المحلٌة
فسوف تواجه خطر عرض بٌانات قدٌمة للمستخدمٌن مما قد ٌجعلك عرضة ألن ٌتعامل مستخدمو تطبٌقك مع عدة نسخ
غٌر متزامنة من البٌانات
ومع أخذ هذا التحذٌر بعٌن االعتبار دعنا نتحدث عن سٌنارٌو ٌكون معقوال من أجل كمٌات كبٌرة من البٌانات ٌتم تخزٌنها
محلٌا .قد ٌكون لدٌك عدد من الجداول الثابتة تكون موجودة فقط من أجل توفٌر بٌانات تطبٌع وغالبا ما تعرف بجداول
البحث وأنا اتعامل ٌومٌا مع العدٌد من جداول البحث التً تحتوي على مجموعات مختلفة من البٌانات محددة بالسنة بما ان
المستخدمٌن ٌمكن ان ٌتعاملوا مع بٌانات من السنوات السابقة ربما نحتاج إلى تقدٌم بٌانات بحث من اٌة سنة فً أي وقت
وٌتشعب هذا السٌنارٌو فً حالة الزبائن الذٌن ٌتعاملون منذ فترة طوٌلة فهؤالء ٌكون لهم بٌانات بحث أكثر من الزبائن
الجدد وقد تصبح األمور أسوأ بسبب طبٌعة البٌانات فالزبائن األكبر ٌمٌلون ألن ٌكون لهم إدخاالت أكثر فً جداول البحث
لكل عام وهذا سٌؤدي إلى بعض المشاكل المتعلقة باألداء بما ان جداول بٌانات ADO .netال تتدرج جٌدا من ناحٌة
السرعة عندما ٌتم التعامل معها بسذاجة ففً بٌئة التطوٌر ٌكون لدٌنا لكل جدول بحث عدد قلٌل من السجالت وفً
االختبار العملً قد ٌكون هناك أكثر من 09999سجل فً الجدول الواحد وبهذا ٌنخفض األداء بصورة ملحوظة مع
مجموعات البٌانات األكبر
وكم سٌتطلب ذلك؟ هذا ٌعتمد على بعض العوامل األول هو عدد السطور فً السجل والثانً هو هل قمت بإنشاء فهرس
Indexقبل أو بعد ان تضٌف البٌانات حٌث ٌظهر الشكل أزمان كبٌرة مرتبطة بإنشاء الفهرس قبل إضافة البٌانات
وبتفحص البٌانات ستجد فرق بٌن %09إلى %09فً الوقت المأخوذ إلنشاء وفهرسة الجداول
ٌمكنك تنفٌذ نفس مقٌاس السرعة باستخدام زر Index Creationفً واجهة قٌاس السرعة Benchmarking UI
والكود المصدري المستخدم فً هذا المقٌاس موجود فً MSDN Code Galleryومن الشكل فً األعلى ٌمكنك رؤٌة
أنه سٌأخذ خمس ثوانً لفهرسة جدول ٌحتوي على 199999سجل .ولفهرسة جدول بٌانات سوف تحتاج لتوفٌر مصفوفة
من أعمدة البٌانات من مفتاح فرٌد للسجالت فً جدول البٌانات مثال:
مع معرفة ان هناك تعقٌدات تتعلق باألداء إلنشاء هذه الفهارس أنصح بنقل عملٌة الفهرسة إلى الخلفٌة وعمل ذلك بشكل ال
متزامن .مع مالحظة أن جداول البٌانات ال تكون آمنة وراثٌا عبر المسارات Not Thread safeلذا علٌك ان تكون
حذرا أثناء القٌام بهذا وٌعتبر العنصر BackgroundWorkerخٌارا جمٌال لهذا الهدف بما أن جدول البٌانات لن ٌكون
متوفرا للمسار الرئٌسً لغاٌة اكتمال عملٌة إنشاء الجدول وفهرسته ونشره .وسٌصبح السؤال هل تستحق المنفعة المكتسبة
هذه الخمس ثوانً تأخٌر؟ دعنا نرى الفرق فً األداء بٌن عدة طرق لالستعالم من جدول بٌانات
End Sub
أول شئ نفعله فً جمٌع اختبارات االداء هو استدعاء االختبار وتنفٌذه على جدول البٌانات من أجل عنصر وحٌد هذه
العملٌة تجبر المكتبات المطلوبة على التحمٌل وتجنبنا الحصول على زمن تنفٌذ عالً أثناء االختبار األول بحٌث ٌمكننا
بعدها تنفٌذ االختبار من اجل جداول تحتوي على 19إلى 1999999سجل فً كل اختبار اداء وٌتم اعادة العملٌة عدة
مرات وٌؤخذ متوسط النتائج مما ٌخفف أٌة نتائج متأثرة بظروف غٌر متوقعة ثم ٌتم حفظ النتائج فً مل CSVفً المجلد
Bin\Debug
ٌحتوي اختبار استعالمات لٌنك Linqعلى سطر كود اضافً من اجل فرض تنفٌذ االستعالم فبما أن لٌنك تستخدم
استعالما مؤجال فستبدو ستبدو استعالمات لٌنك بدون هذا السطر وكأنها فورٌة بدون ان تعٌد النتٌجة فً الحقٌقة وقد قمت
بتنفٌذ استعالم لٌنك من أجل جداول مفهرسة وغٌر مفهرسة وهذا مثال ٌوضح انشاء استعالم لٌنك على داتاسٌت
Private Function TestLinqSearch(ByVal dt As DataTable, ByVal key As String) As Integer
Dim sw As New Stopwatch
)(sw.Start
)Dim result = From r In dt Where r(0) = key Select r(1
Dim output As String = result(0).ToString
)(sw.Stop
)Console.WriteLine(output
Return sw.ElapsedTicks
End Function
ٌبدا السطر فً األعلى بـ Dim Resultإلنشاء استعالم لٌنك ومع ذلك فبسبب االستعالم المتأخر ال ٌتم تقٌٌمه حتى السطر
الذي ٌبدأ بـ Dim outputوهذا االستدعاء الثانً مطلوب من اجل الحصول على صورة دقٌقة لألداء.
كلما كان ممكنا أزلت األعمال الزائدة مثل دمج النصوص والحصول على مرجع للعمود عندما ٌتم االشارة الٌه بواسطة
االسم من كود قٌاس االداء وهذا بالطبع ال ٌعكس حقٌقة الطرٌقة التً تستخدم فٌها جداول البٌانات فً العالم الحقٌقً وقد
تعمدت ذلك من أجل الحصول على افضل اداء ممكن من جدول البٌانات
واخٌرا جمٌع نتائج االختبارات هً بالتٌك tickولٌس بالمٌللً ثانٌة والسبب فً ذلك بسٌط وهو أن نتائج البحث فً
الجداول المفهرسة والقوامٌس تكون سرٌعة جدا بحٌث ال ٌمكن قٌاسها بمجال المٌللً ثانٌة .الحظ أٌضا ان فهرسة الجدول
تقدم أفضلٌة ضئٌلة الستعالم لٌنك وتأثٌر فهرسة الجدول عند التصفٌة بعدة أعمدة ٌتطلب استكشافا أكثر
ثالثا نظرا لسٌنارٌو الحصول على سجل واحد فقط من المجموعة تصبح عملٌة تحوٌل جدول بٌاناتك إلى قاموس هو البدٌل
األسرع واألكثر قابلٌة للقٌاس وفً سٌنارٌو أنه ٌوجد أكثر من سجل ستتم استعادته ٌجب أخذ لٌنك بجدٌة ونرى بوضوح
أن ماٌكروسوفت قد قامت بالعمل الكثٌر من أجل ضبط أداء لٌنك حتى من أجل مجموعات بٌانات كبٌرة وبما ان أي خٌار
غٌر DataTable.Selectسٌتعامل بشكل جٌد مع مجموعات البٌانات الكبٌرة قم بتنظٌف كودك األساسً من
DataTable.Select
حول نتائج االختبار سترى أن األعمدة مرتبة بحسب المدة التً تستغرقها كل عملٌة بما أننً أقترح القاموس dictionary
كبدٌل عن جدول البٌانات DataTableوقد ضمنت أٌضا تكلفة إنشاء قاموس ) Dictionary(Of String, Stringلٌضم
نفس البٌانات التً ٌتضمنها جدول البٌانات ستالحظ أن إنشاء قاموس أقل تكلفة من تنفٌذ DataTable.Selectوحٌدة من
أجل البٌانات وطالما أنك تستعلم من البٌانات أكثر من مرة ٌثبت أن إنشاء قاموس هً العملٌة الرابحة وتجدر المالحظة أن
هناك بعض االختالفات فً القاموس بناء على نوع المفتاح .ومع ذلك فإن استخدمت قاموسا او جدوال مفهرسا ستكلفك
عملٌة إعادة هٌكلة البٌانات إلى هٌكل أكثر كفاءة نفقات كثٌرة وهنا ٌبرز لٌنك كخٌار أفضل من منظور األداء إضافة إلى
أن الكود سٌصبح أسهل وأصغر وأكثر قابلٌة للقراءة من قبل أي شخص معتاد على عملٌات قواعد البٌانات
التجميع
حتى اآلن تكون النتٌجة 1الستعالمات لٌنك و 9لطرائق جدول البٌانات سنرى فً القسم الثانً إن كانت ADO .net
DataTableتستطٌع تخلٌص نفسها والبقاء ضمن المنافسة فً التجمٌع .سوف نستخدم هنا نفس جدول البٌانات األساسً
الذي استخدمناه حتى اآلن ( جدول بٌانات غٌر مفهرس مع عمودٌن وعدد nمن السجالت ) بحٌث ننفذ هنا ثالث عملٌات
تجمٌع أساسٌة Minو Maxو AVGبحٌث ستبدو كالتالً
Dim linqMinResult = (From r In dt Select r.Field(Of Int32)("Value")).Min
Dim linqMaxResult = (From r In dt Select r.Field(Of Int32)("Value")).Max
Dim linqAvgResult = (From r In dt Select r.Field(Of Int32)("Value")).Average
)"" Dim computeMinResult = dt.Compute("MIN(Value)",
)"" Dim computeMaxResult = dt.Compute("MAX(Value)",
ربما ٌكون هذا هو الوقت المالئم من أجل قضٌة أخٌرة بما أننً لست خبٌرا بلٌنك فأول ستة استعالمات لٌنك فً هذا
المقال موجودة فً msdnومع ذلك فلٌست جمٌع استعالمات لٌنك أنشأت متساوٌة وقد كان من اللطف من زمٌل أن ٌشٌر
إلى المتغٌر التالً لتجمٌع maxالستعراض هذه الحقٌقة
قمت بتضمٌن نتائج هذا االستعالم فً مخطط للتجمٌع maxمسمى ) Linq Max (slowستالحظ مع أن االستعالمات
متكافئة قواعدٌا فاالستعالم الثانً ٌتم تنفٌذه ثالث مرات أبطأ من استعالم لٌنك السابق وسبب الفرق فً األداء هو أن
النسخة السرٌعة تستخدم نسخة محملة Overloadمن maxال تحتاج ألي محدد والقاعدة هنا هً ان استخدام Linq to
Datasetهو أفضل من استخدام لٌنك تستخدم selectبشكل صرٌح ومع فروقات األداء فاالستعالمات تعطً قٌاسات
متشابهة
و ال ٌبدو الفائز فً هذه الحالٌة بصورة جلٌة كما ٌتبٌن من المخططات ولكن تمٌل لٌنك ألن تنفذ بشكل أسرع قلٌال من
أجل Minوأبطأ قلٌال من أجل maxو avgوبعد رؤٌة التقدم الكبٌر فً األداء الذي تقدمه لٌنك عند القٌام بالبحث مقارنة
مع جداول البٌانات توقعت رؤٌة قٌاسات محسنة بشكل أفضل مع داالت التجمٌع
وفً النهاٌة إن كنت تستخدم جداول البٌانات تعتبر طرٌقة Selectأسوأ طرٌقة ٌمكن عملها لتقلٌل تدرجٌة تطبٌقك وقد
ناقشنا بعض البدائل هنا مثل Linqوفهرسة الجداول حتى نتمكن من استخدام row.findأو تركٌب جدول البٌانات ضمن
Generic Collectionفأي من هذه الطرق سوف ٌنفذ األوامر أسرع من االستعالم عن مجموعة من السجالت ذات
حجم معقول وربما تحتاج لمزاوجة مجموعات السجالت أكثر ما ٌمكن من أجل تسرٌع استعالم وتجمٌع السجالت
http://msdn.microsoft.com/ar-sy/library/dd364983(en-us).aspx
www.vb4arab.com