نتائج البحث وقضايا الأداء والأداء

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

نتائج البحث وقضايا الأداء والأداء

خيار الترحيل رقم 1

إن أبسط خيار يتبادر إلى الذهن هو عرض نتائج البحث صفحة تلو الأخرى في شكلها الأكثر كلاسيكية.

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

  • الحصول على صفوف للصفحة الحالية.
  • احسب العدد الإجمالي للأسطر المقابلة لمعايير البحث - وهذا ضروري لعرض الصفحات.

دعونا نلقي نظرة على الاستعلام الأول باستخدام قاعدة بيانات MS SQL للاختبار كمثال عمل مغامر لخادم 2016. لهذا الغرض سوف نستخدم الجدول Sales.SalesOrderHeader:

SELECT * FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

سيعرض الاستعلام أعلاه أول 50 طلبًا من القائمة، مرتبة حسب تاريخ الإضافة تنازليًا، بمعنى آخر، أحدث 50 طلبًا.

يتم تشغيله بسرعة على قاعدة الاختبار، ولكن دعونا نلقي نظرة على خطة التنفيذ وإحصائيات الإدخال/الإخراج:

نتائج البحث وقضايا الأداء والأداء

Table 'SalesOrderHeader'. Scan count 1, logical reads 698, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

يمكنك الحصول على إحصائيات الإدخال/الإخراج لكل استعلام عن طريق تشغيل الأمر SET STATISTICS IO ON في وقت تشغيل الاستعلام.

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

نتائج البحث وقضايا الأداء والأداء

Table 'SalesOrderHeader'. Scan count 1, logical reads 165, physical reads 0, read-ahead reads 5, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

من الواضح أنه أصبح أفضل بكثير. ولكن هل تم حل جميع المشاكل؟ لنغير الاستعلام للبحث عن الطلبات التي تتجاوز فيها التكلفة الإجمالية للسلع 100 دولار:

SELECT * FROM Sales.SalesOrderHeader
WHERE SubTotal > 100
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

نتائج البحث وقضايا الأداء والأداء

Table 'SalesOrderHeader'. Scan count 1, logical reads 1081, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

لدينا موقف مضحك: خطة الاستعلام ليست أسوأ بكثير من الخطة السابقة، ولكن العدد الفعلي للقراءات المنطقية هو تقريبًا ضعف ما هو عليه عند إجراء مسح كامل للجدول. هناك طريقة للخروج - إذا أنشأنا فهرسًا مركبًا من فهرس موجود بالفعل وأضفنا السعر الإجمالي للسلع كحقل ثانٍ، فسنحصل مرة أخرى على 165 قراءة منطقية:

CREATE INDEX IX_SalesOrderHeader_OrderDate_SubTotal on Sales.SalesOrderHeader(OrderDate, SubTotal);

يمكن أن تستمر هذه السلسلة من الأمثلة لفترة طويلة، ولكن الفكرتين الرئيسيتين اللتين أريد التعبير عنهما هنا هما:

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

لننتقل الآن إلى الاستعلام الثاني المذكور في البداية - وهو الاستعلام الذي يحسب عدد السجلات التي تستوفي معيار البحث. لنأخذ نفس المثال - البحث عن الطلبات التي تزيد قيمتها عن 100 دولار:

SELECT COUNT(1) FROM Sales.SalesOrderHeader
WHERE SubTotal > 100

وبالنظر إلى المؤشر المركب المشار إليه أعلاه، نحصل على:

نتائج البحث وقضايا الأداء والأداء

Table 'SalesOrderHeader'. Scan count 1, logical reads 698, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

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

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

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

خيار الترحيل رقم 2

لنفترض أن المستخدمين لا يهتمون بمعرفة العدد الإجمالي للكائنات التي تم العثور عليها. دعونا نحاول تبسيط صفحة البحث:

نتائج البحث وقضايا الأداء والأداء
في الواقع، الشيء الوحيد الذي تغير هو أنه لا توجد طريقة للانتقال إلى أرقام صفحات محددة، والآن لا يحتاج هذا الجدول إلى معرفة العدد الذي يمكن أن يكون موجودًا لعرضه. لكن السؤال الذي يطرح نفسه - كيف يعرف الجدول ما إذا كانت هناك بيانات للصفحة التالية (من أجل عرض الرابط "التالي" بشكل صحيح)؟

الجواب بسيط للغاية: يمكنك قراءة سجل واحد إضافي من قاعدة البيانات مما هو مطلوب للعرض، وسيظهر وجود هذا السجل "الإضافي" ما إذا كان هناك جزء تالي. بهذه الطريقة، تحتاج فقط إلى تشغيل طلب واحد للحصول على صفحة واحدة من البيانات، مما يؤدي إلى تحسين الأداء بشكل كبير وتسهيل دعم هذه الوظيفة. في ممارستي، كانت هناك حالة عندما أدى رفض حساب العدد الإجمالي للسجلات إلى تسريع تسليم النتائج بمقدار 4-5 مرات.

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

الفروق الدقيقة في تنفيذ الترحيل

تستخدم جميع أمثلة الاستعلام الواردة أعلاه أسلوب "الإزاحة + العد"، عندما يحدد الاستعلام نفسه ترتيب صفوف النتائج وعدد الصفوف التي يجب إرجاعها. أولاً، دعونا نلقي نظرة على أفضل السبل لتنظيم تمرير المعلمات في هذه الحالة. في الممارسة العملية، وجدت عدة طرق:

  • الرقم التسلسلي للصفحة المطلوبة (pageIndex)، حجم الصفحة (pageSize).
  • الرقم التسلسلي للسجل الأول الذي سيتم إرجاعه (startIndex)، الحد الأقصى لعدد السجلات في النتيجة (count).
  • الرقم التسلسلي للسجل الأول الذي سيتم إرجاعه (startIndex)، والرقم التسلسلي للسجل الأخير الذي سيتم إرجاعه (endIndex).

للوهلة الأولى قد يبدو أن هذا أمر أساسي للغاية بحيث لا يوجد فرق. ولكن هذا ليس كذلك - الخيار الأكثر ملاءمة وعالمية هو الثاني (startIndex، العد). هناك عدة أسباب لذلك:

  • بالنسبة لطريقة تدقيق الإدخال 1+ الموضحة أعلاه، فإن الخيار الأول مع pageIndex وpageSize غير مريح للغاية. على سبيل المثال، نريد عرض 50 مشاركة في كل صفحة. وفقا للخوارزمية المذكورة أعلاه، تحتاج إلى قراءة سجل واحد أكثر من اللازم. إذا لم يتم تنفيذ هذا "+1" على الخادم، فسيتبين أنه بالنسبة للصفحة الأولى، يجب علينا طلب السجلات من 1 إلى 51، وللصفحة الثانية - من 51 إلى 101، وما إلى ذلك. إذا قمت بتحديد حجم الصفحة 51 وقمت بزيادة pageIndex، فستعود الصفحة الثانية من 52 إلى 102، إلخ. وفقًا لذلك، في الخيار الأول، الطريقة الوحيدة لتنفيذ زر للانتقال إلى الصفحة التالية بشكل صحيح هي مطالبة الخادم بمراجعة السطر "الإضافي"، والذي سيكون فارقًا بسيطًا للغاية.
  • الخيار الثالث غير منطقي على الإطلاق، لأنه لتشغيل الاستعلامات في معظم قواعد البيانات، ستظل بحاجة إلى تمرير العد بدلاً من فهرس السجل الأخير. قد يكون طرح startIndex من endIndex عملية حسابية بسيطة، لكنها غير ضرورية هنا.

الآن يجب أن نصف عيوب تنفيذ الترحيل من خلال "الإزاحة + الكمية":

  • سيكون استرداد كل صفحة لاحقة أكثر تكلفة وأبطأ من الصفحة السابقة، لأن قاعدة البيانات ستظل بحاجة إلى مراجعة جميع السجلات "من البداية" وفقًا لمعايير البحث والفرز، ثم التوقف عند الجزء المطلوب.
  • لا يمكن لجميع أنظمة إدارة قواعد البيانات (DBMS) دعم هذا النهج.

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

SELECT * FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

وفي السجل الأخير حصلنا على قيمة تاريخ الطلب “2014-06-29”. ثم للحصول على الصفحة التالية، يمكنك محاولة القيام بذلك:

SELECT * FROM Sales.SalesOrderHeader
WHERE OrderDate < '2014-06-29'
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

تكمن المشكلة في أن OrderDate هو حقل غير فريد ومن المحتمل أن يفتقد الشرط المحدد أعلاه الكثير من الصفوف المطلوبة. لإضافة الوضوح إلى هذا الاستعلام، تحتاج إلى إضافة حقل فريد إلى الشرط (بافتراض أن 75074 هي القيمة الأخيرة للمفتاح الأساسي من الجزء الأول):

SELECT * FROM Sales.SalesOrderHeader
WHERE (OrderDate = '2014-06-29' AND SalesOrderID < 75074)
   OR (OrderDate < '2014-06-29')
ORDER BY OrderDate DESC, SalesOrderID DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

سيعمل هذا الخيار بشكل صحيح، ولكن بشكل عام سيكون من الصعب تحسينه نظرًا لأن الشرط يحتوي على عامل التشغيل OR. إذا زادت قيمة المفتاح الأساسي مع زيادة OrderDate، فيمكن تبسيط الشرط عن طريق ترك عامل التصفية فقط بواسطة SalesOrderID. ولكن إذا لم يكن هناك ارتباط صارم بين قيم المفتاح الأساسي والحقل الذي يتم فرز النتيجة من خلاله، فلا يمكن تجنب هذا OR في معظم أنظمة إدارة قواعد البيانات. الاستثناء الذي أعرفه هو PostgreSQL، الذي يدعم بشكل كامل مقارنة الصف، ويمكن كتابة الشرط أعلاه كـ "WHERE (OrderDate, SalesOrderID) < ('2014-06-29'، 75074)". بالنظر إلى مفتاح مركب بهذين الحقلين، فإن استعلامًا مثل هذا يجب أن يكون سهلاً إلى حد ما.

ويمكن العثور على نهج بديل ثان، على سبيل المثال، في واجهة برمجة تطبيقات التمرير ElasticSearch أو كوزموس دي بي - عندما يقوم الطلب، بالإضافة إلى البيانات، بإرجاع معرف خاص يمكنك من خلاله الحصول على الجزء التالي من البيانات. إذا كان لهذا المعرف عمر غير محدود (كما هو الحال في Comsos DB)، فهذه طريقة رائعة لتنفيذ الترحيل مع الانتقال المتسلسل بين الصفحات (الخيار رقم 2 المذكور أعلاه). عيوبه المحتملة: غير مدعوم في كافة أنظمة إدارة قواعد البيانات؛ قد يكون لمعرف المجموعة التالية الناتج عمر محدود، وهو غير مناسب بشكل عام لتنفيذ تفاعل المستخدم (مثل واجهة برمجة تطبيقات التمرير ElasticSearch).

التصفية المعقدة

دعونا تعقيد المهمة أكثر. لنفترض أن هناك متطلبًا لتنفيذ ما يسمى بالبحث متعدد الأوجه، وهو أمر مألوف جدًا للجميع من المتاجر عبر الإنترنت. الأمثلة المذكورة أعلاه المستندة إلى جدول الطلبات ليست توضيحية جدًا في هذه الحالة، لذا دعنا ننتقل إلى جدول المنتج من قاعدة بيانات AdventureWorks:

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

على سبيل المثال، إذا قمنا بتحديد فئة الدراجات واللون الأسود في هذا المثال، فسيظهر الجدول الدراجات السوداء فقط، ولكن:

  • بالنسبة لكل معيار في مجموعة الفئات، سيتم عرض عدد المنتجات من تلك الفئة باللون الأسود.
  • لكل معيار من مجموعة "الألوان" سيتم عرض عدد الدراجات الهوائية من هذا اللون.

فيما يلي مثال لإخراج النتيجة لمثل هذه الشروط:

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

الآن دعونا نتخيل كيف يمكن تنفيذ ذلك على أساس علائقي. ستتطلب كل مجموعة من المعايير، مثل الفئة واللون، استعلامًا منفصلاً:

SELECT pc.ProductCategoryID, pc.Name, COUNT(1) FROM Production.Product p
  INNER JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID
  INNER JOIN Production.ProductCategory pc ON ps.ProductCategoryID = pc.ProductCategoryID
WHERE p.Color = 'Black'
GROUP BY pc.ProductCategoryID, pc.Name
ORDER BY COUNT(1) DESC

نتائج البحث وقضايا الأداء والأداء

SELECT Color, COUNT(1) FROM Production.Product p
  INNER JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID
WHERE ps.ProductCategoryID = 1 --Bikes
GROUP BY Color
ORDER BY COUNT(1) DESC

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

عادة بعد هذه التصريحات يعرض علي بعض الحلول وهي:

  • دمج كافة أعداد الكميات في استعلام واحد. من الناحية الفنية، يكون هذا ممكنًا باستخدام الكلمة الأساسية UNION، ولكنه لن يساعد كثيرًا في الأداء - سيظل يتعين على قاعدة البيانات تنفيذ كل جزء من الأجزاء من البداية.
  • كميات ذاكرة التخزين المؤقت. يتم اقتراح هذا لي تقريبًا في كل مرة أصف فيها مشكلة. التحذير هو أن هذا مستحيل بشكل عام. لنفترض أن لدينا 10 "أوجه"، لكل منها 5 قيم. وهذا وضع "متواضع" للغاية مقارنة بما يمكن رؤيته في نفس المتاجر عبر الإنترنت. يؤثر اختيار عنصر وجه واحد على الكميات الموجودة في 9 عناصر أخرى، وبعبارة أخرى، يمكن أن تكون الكميات مختلفة لكل مجموعة من المعايير. في مثالنا، هناك إجمالي 50 معيارًا يمكن للمستخدم تحديدها، لذلك سيكون هناك 250 مجموعة محتملة. لا توجد ذاكرة أو وقت كافٍ لملء مثل هذه المجموعة من البيانات. هنا يمكنك الاعتراض والقول أنه ليست كل المجموعات حقيقية وأن المستخدم نادرًا ما يختار أكثر من 5-10 معايير. نعم، من الممكن القيام بالتحميل البطيء والتخزين المؤقت لكمية فقط مما تم تحديده، ولكن كلما زاد عدد الاختيارات، قلت كفاءة ذاكرة التخزين المؤقت هذه وأصبحت مشاكل وقت الاستجابة أكثر وضوحًا (خاصة إذا كان تتغير مجموعة البيانات بانتظام).

لحسن الحظ، كان لهذه المشكلة منذ فترة طويلة حلول فعالة للغاية تعمل بشكل يمكن التنبؤ به على كميات كبيرة من البيانات. بالنسبة لأي من هذه الخيارات، فمن المنطقي تقسيم إعادة حساب الواجهات واستلام صفحة النتائج إلى مكالمتين متوازيتين للخادم وتنظيم واجهة المستخدم بطريقة تجعل تحميل البيانات حسب الواجهات "لا يتداخل" مع عرض نتائج البحث.

  • نادرًا ما يتم استدعاء إعادة حساب كاملة لـ "الجوانب" قدر الإمكان. على سبيل المثال، لا تقم بإعادة حساب كل شيء في كل مرة تتغير فيها معايير البحث، ولكن بدلاً من ذلك ابحث عن العدد الإجمالي للنتائج التي تطابق الشروط الحالية واطلب من المستخدم إظهارها - "تم العثور على 1425 سجلاً، هل تريد العرض؟" يمكن للمستخدم إما الاستمرار في تغيير مصطلحات البحث أو النقر فوق الزر "إظهار". فقط في الحالة الثانية سيتم تنفيذ جميع طلبات الحصول على النتائج وإعادة حساب الكميات على جميع "الأوجه". في هذه الحالة، كما ترون بسهولة، سيتعين عليك التعامل مع طلب للحصول على العدد الإجمالي للنتائج وتحسينها. يمكن العثور على هذه الطريقة في العديد من المتاجر الصغيرة عبر الإنترنت. ومن الواضح أن هذا ليس حلا سحريا لهذه المشكلة، ولكن في الحالات البسيطة يمكن أن يكون حلا وسطا جيدا.
  • استخدم محركات البحث للعثور على النتائج وإحصاء الأوجه، مثل Solr وElasticSearch وSphinx وغيرها. تم تصميمها جميعًا لبناء "الجوانب" والقيام بذلك بكفاءة عالية بفضل المؤشر المقلوب. كيف تعمل محركات البحث، ولماذا تكون في مثل هذه الحالات أكثر فعالية من قواعد البيانات ذات الأغراض العامة، وما هي الممارسات والمزالق الموجودة - وهذا موضوع لمقالة منفصلة. هنا أود أن ألفت انتباهكم إلى حقيقة أن محرك البحث لا يمكن أن يكون بديلاً لمخزن البيانات الرئيسي، بل يتم استخدامه كإضافة: تتم مزامنة أي تغييرات في قاعدة البيانات الرئيسية ذات الصلة بالبحث في فهرس البحث؛ يتفاعل محرك البحث عادةً مع محرك البحث فقط ولا يصل إلى قاعدة البيانات الرئيسية. إحدى أهم النقاط هنا هي كيفية تنظيم هذه المزامنة بشكل موثوق. كل هذا يتوقف على متطلبات "وقت رد الفعل". إذا كان الوقت بين التغيير في قاعدة البيانات الرئيسية و"إظهاره" في البحث ليس حرجًا، فيمكنك إنشاء خدمة تبحث عن السجلات التي تم تغييرها مؤخرًا كل بضع دقائق وفهرستها. إذا كنت تريد أقصر وقت استجابة ممكن، يمكنك تنفيذ شيء من هذا القبيل صندوق الصادر للمعاملات لإرسال التحديثات إلى خدمة البحث.

النتائج

  1. يعد تنفيذ الترحيل من جانب الخادم تعقيدًا كبيرًا ويكون منطقيًا فقط لمجموعات البيانات سريعة النمو أو الكبيرة. لا توجد وصفة دقيقة تمامًا لكيفية تقييم "الشركات الكبيرة" أو "السريعة النمو"، لكنني سأتبع هذا النهج:
    • إذا كان تلقي مجموعة كاملة من البيانات، مع مراعاة وقت الخادم ونقل الشبكة، يناسب متطلبات الأداء بشكل طبيعي، فلا فائدة من تنفيذ الترحيل على جانب الخادم.
    • قد يكون هناك موقف لا يُتوقع فيه حدوث مشكلات في الأداء في المستقبل القريب، نظرًا لوجود القليل من البيانات، ولكن جمع البيانات يتزايد باستمرار. إذا لم تعد مجموعة من البيانات في المستقبل تلبي النقطة السابقة، فمن الأفضل أن تبدأ الترحيل على الفور.
  2. إذا لم يكن هناك شرط صارم من جانب الشركة لعرض العدد الإجمالي للنتائج أو لعرض أرقام الصفحات، ولا يحتوي نظامك على محرك بحث، فمن الأفضل عدم تنفيذ هذه النقاط والنظر في الخيار رقم 2.
  3. إذا كان هناك مطلب واضح للبحث متعدد الأوجه، فلديك خياران دون التضحية بالأداء:
    • لا تقم بإعادة حساب جميع الكميات في كل مرة تتغير فيها معايير البحث.
    • استخدم محركات البحث مثل Solr و ElasticSearch و Sphinx وغيرها. ولكن ينبغي أن يكون مفهوما أنه لا يمكن أن يكون بديلا لقاعدة البيانات الرئيسية، ويجب استخدامه كإضافة إلى وحدة التخزين الرئيسية لحل مشاكل البحث.
  4. أيضًا، في حالة البحث متعدد الأوجه، فمن المنطقي تقسيم استرجاع صفحة نتائج البحث والعد إلى طلبين متوازيين. قد يستغرق عد الكميات وقتًا أطول من الحصول على النتائج، بينما تكون النتائج أكثر أهمية للمستخدم.
  5. إذا كنت تستخدم قاعدة بيانات SQL للبحث، فإن أي تغيير في التعليمات البرمجية يتعلق بهذا الجزء يجب أن يتم اختباره جيدًا من حيث الأداء على الكمية المناسبة من البيانات (التي تتجاوز الحجم في قاعدة البيانات المباشرة). يُنصح أيضًا باستخدام مراقبة وقت تنفيذ الاستعلام في جميع مثيلات قاعدة البيانات، وخاصة في النسخة "المباشرة". حتى لو كان كل شيء على ما يرام مع خطط الاستعلام في مرحلة التطوير، مع نمو حجم البيانات، فقد يتغير الوضع بشكل ملحوظ.

المصدر: www.habr.com

إضافة تعليق