مشکلات خروجی نتایج جستجو و عملکرد

یکی از سناریوهای معمول در همه برنامه هایی که با آن آشنا هستیم، جستجوی داده ها بر اساس معیارهای خاص و نمایش آن ها به شکلی خوانا است. همچنین ممکن است گزینه های دیگری برای مرتب سازی، گروه بندی و صفحه بندی وجود داشته باشد. این کار، از نظر تئوری، بی اهمیت است، اما هنگام حل آن، بسیاری از توسعه دهندگان اشتباهات زیادی مرتکب می شوند که بعداً باعث کاهش بهره وری می شود. بیایید سعی کنیم گزینه های مختلفی را برای حل این مشکل در نظر بگیریم و توصیه هایی را برای انتخاب مؤثرترین اجرا تدوین کنیم.

مشکلات خروجی نتایج جستجو و عملکرد

گزینه صفحه بندی شماره 1

ساده ترین گزینه ای که به ذهن می رسد نمایش صفحه به صفحه نتایج جستجو در کلاسیک ترین شکل آن است.

مشکلات خروجی نتایج جستجو و عملکرد
فرض کنید برنامه شما از یک پایگاه داده رابطه ای استفاده می کند. در این صورت، برای نمایش اطلاعات در این فرم، باید دو پرس و جوی SQL را اجرا کنید:

  • دریافت ردیف برای صفحه فعلی.
  • تعداد کل خطوط مربوط به معیارهای جستجو را محاسبه کنید - این برای نمایش صفحات ضروری است.

بیایید به اولین پرس و جو با استفاده از پایگاه داده آزمایشی MS SQL به عنوان مثال نگاه کنیم AdventureWorks برای سرور 2016 برای این منظور از جدول Sales.SalesOrderHeader استفاده می کنیم:

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

پرس و جوی بالا 50 سفارش اول لیست را که بر اساس تاریخ نزولی اضافه مرتب شده اند، به عبارت دیگر، 50 سفارش اخیر را برمی گرداند.

به سرعت در پایه آزمایشی اجرا می شود، اما بیایید به برنامه اجرا و آمار I/O نگاه کنیم:

مشکلات خروجی نتایج جستجو و عملکرد

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.

این واقعیت که پرس و جو از کل ایندکس عبور می کند تعجب آور نیست، زیرا قسمت SubTotal در موقعیت اول قرار ندارد، بنابراین پرس و جو نمی تواند از آن استفاده کند. مشکل با اضافه کردن یک شاخص دیگر در قسمت SubTotal حل می شود و در نتیجه تنها 48 خواندن منطقی می دهد.

شما می توانید چند مثال دیگر از درخواست های شمارش مقادیر ارائه دهید، اما اصل یکسان است: دریافت یک قطعه داده و شمارش کل مبلغ دو درخواست اساساً متفاوت هستندو هر کدام برای بهینه سازی اقدامات خاص خود را می طلبد. به طور کلی، شما نمی توانید ترکیبی از ایندکس ها را پیدا کنید که برای هر دو پرس و جو به یک اندازه خوب کار کند.

بر این اساس، یکی از الزامات مهمی که باید هنگام توسعه چنین راه حل جستجویی روشن شود این است که آیا دیدن تعداد کل اشیاء یافت شده برای یک تجارت واقعا مهم است یا خیر. اغلب اتفاق می افتد که نه. و پیمایش بر اساس شماره صفحات خاص، به نظر من، راه حلی با دامنه بسیار باریک است، زیرا اکثر سناریوهای صفحه بندی شبیه "رفتن به صفحه بعدی" هستند.

گزینه صفحه بندی شماره 2

بیایید فرض کنیم که کاربران به دانستن تعداد کل اشیاء یافت شده اهمیتی نمی دهند. بیایید سعی کنیم صفحه جستجو را ساده کنیم:

مشکلات خروجی نتایج جستجو و عملکرد
در واقع تنها چیزی که تغییر کرده این است که هیچ راهی برای پیمایش به شماره صفحات خاصی وجود ندارد و اکنون این جدول برای نمایش آن نیازی به دانستن تعداد آن ندارد. اما این سوال مطرح می شود - جدول چگونه می داند که آیا داده هایی برای صفحه بعدی وجود دارد (برای نمایش صحیح پیوند "بعدی")؟

پاسخ بسیار ساده است: شما می توانید از پایگاه داده یک رکورد بیشتر از آنچه برای نمایش نیاز است بخوانید، و وجود این رکورد "اضافی" نشان می دهد که آیا قسمت بعدی وجود دارد یا خیر. به این ترتیب، شما فقط باید یک درخواست را برای دریافت یک صفحه داده اجرا کنید، که به طور قابل توجهی عملکرد را بهبود می بخشد و پشتیبانی از چنین عملکردی را آسان تر می کند. در عمل من، موردی وجود داشت که امتناع از شمارش تعداد کل رکوردها، تحویل نتایج را 4-5 برابر افزایش داد.

چندین گزینه رابط کاربری برای این رویکرد وجود دارد: دستورات "back" و "forward"، مانند مثال بالا، یک دکمه "load more" که به سادگی یک بخش جدید به نتایج نمایش داده شده اضافه می کند، "بی نهایت پیمایش"، که کار می کند. بر اساس اصل "بارگذاری بیشتر" "، اما سیگنال دریافت قسمت بعدی این است که کاربر تمام نتایج نمایش داده شده را تا انتها پیمایش کند. راه حل بصری هرچه که باشد، اصل نمونه گیری داده ها ثابت می ماند.

تفاوت های ظریف پیاده سازی صفحه بندی

تمام نمونه‌های پرس و جو ارائه شده در بالا از رویکرد "offset + count" استفاده می‌کنند، زمانی که خود کوئری مشخص می‌کند که ردیف‌های نتیجه به چه ترتیبی و چند ردیف باید برگردانده شوند. ابتدا، بیایید نحوه سازماندهی بهترین ارسال پارامتر را در این مورد بررسی کنیم. در عمل به چندین روش برخورد کردم:

  • شماره سریال صفحه درخواستی (pageIndex)، اندازه صفحه (pageSize).
  • شماره سریال اولین رکوردی که باید برگردانده شود (startIndex)، حداکثر تعداد رکوردها در نتیجه (شمارش).
  • شماره ترتیب اولین رکوردی که باید برگردانده شود (startIndex)، شماره دنباله آخرین رکوردی که باید برگردانده شود (endIndex).

در نگاه اول ممکن است به نظر برسد که این بسیار ابتدایی است که هیچ تفاوتی وجود ندارد. اما این چنین نیست - راحت ترین و جهانی ترین گزینه دوم است (startIndex، count). چند دلیل برای این وجود دارد:

  • برای رویکرد تصحیح ورودی +1 که در بالا ارائه شد، اولین گزینه با pageIndex و pageSize بسیار ناخوشایند است. برای مثال می خواهیم در هر صفحه 50 پست نمایش دهیم. طبق الگوریتم بالا باید یک رکورد بیشتر از حد لازم بخوانید. اگر این "+1" روی سرور اجرا نشود، معلوم می شود که برای صفحه اول باید رکوردهایی از 1 تا 51، برای دوم - از 51 تا 101 و غیره درخواست کنیم. اگر اندازه صفحه 51 را مشخص کنید و pageIndex را افزایش دهید، صفحه دوم از 52 به 102 و غیره باز می گردد. بر این اساس، در گزینه اول، تنها راه برای اجرای صحیح یک دکمه برای رفتن به صفحه بعدی این است که سرور خط "اضافی" را تصحیح کند، که یک تفاوت ظریف بسیار ضمنی خواهد بود.
  • گزینه سوم به هیچ وجه منطقی نیست، زیرا برای اجرای پرس و جوها در بیشتر پایگاه داده ها همچنان باید به جای ایندکس آخرین رکورد، شمارش را پاس کنید. کم کردن startIndex از endIndex ممکن است یک عملیات حسابی ساده باشد، اما در اینجا اضافی است.

اکنون باید معایب پیاده‌سازی صفحه‌بندی را از طریق "offset + quantity" شرح دهیم:

  • بازیابی هر صفحه بعدی گرانتر و کندتر از صفحه قبلی خواهد بود، زیرا پایگاه داده همچنان باید تمام رکوردها را "از ابتدا" طبق معیارهای جستجو و مرتب سازی مرور کند و سپس در قطعه مورد نظر متوقف شود.
  • همه 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 در اکثر DBMS ها قابل اجتناب نیست. استثنایی که من از آن مطلع هستم PostgreSQL است که به طور کامل از مقایسه تاپلی پشتیبانی می کند و شرط فوق را می توان به صورت "WHERE (OrderDate, SalesOrderID) < ('2014-06-29', 75074)" نوشت. با توجه به یک کلید ترکیبی با این دو فیلد، یک پرس و جو مانند این باید نسبتاً آسان باشد.

روش جایگزین دوم را می توان یافت، برای مثال، در API اسکرول ElasticSearch یا Cosmos DB - هنگامی که یک درخواست، علاوه بر داده، یک شناسه ویژه را برمی گرداند که با آن می توانید بخش بعدی داده را دریافت کنید. اگر این شناسه طول عمر نامحدودی دارد (مانند Comsos DB)، پس این یک راه عالی برای پیاده سازی صفحه بندی با انتقال متوالی بین صفحات است (گزینه شماره 2 که در بالا ذکر شد). معایب احتمالی آن: در همه DBMS ها پشتیبانی نمی شود. شناسه تکه بعدی ممکن است طول عمر محدودی داشته باشد، که معمولاً برای اجرای تعامل کاربر مناسب نیست (مانند ElasticSearch scroll API).

فیلترینگ پیچیده

بیایید کار را بیشتر پیچیده کنیم. فرض کنید الزامی برای پیاده سازی به اصطلاح جستجوی وجهی وجود دارد که برای همه از فروشگاه های آنلاین بسیار آشنا است. مثال های بالا بر اساس جدول سفارشات در این مورد چندان گویا نیستند، بنابراین بیایید به جدول Product از پایگاه داده AdventureWorks برویم:

مشکلات خروجی نتایج جستجو و عملکرد
ایده پشت جستجوی وجهی چیست؟ واقعیت این است که برای هر عنصر فیلتر تعداد رکوردهایی که این معیار را برآورده می کنند نشان داده شده است با در نظر گرفتن فیلترهای انتخاب شده در همه دسته های دیگر.

به عنوان مثال، اگر در این مثال دسته دوچرخه و رنگ مشکی را انتخاب کنیم، جدول فقط دوچرخه های مشکی را نشان می دهد، اما:

  • برای هر معیار در گروه دسته بندی ها، تعداد محصولات آن دسته به رنگ مشکی نشان داده می شود.
  • برای هر معیار گروه "رنگ ها"، تعداد دوچرخه های این رنگ نشان داده می شود.

در اینجا مثالی از خروجی نتیجه برای چنین شرایطی آورده شده است:

مشکلات خروجی نتایج جستجو و عملکرد
اگر دسته «لباس» را نیز بررسی کنید، جدول لباس‌های مشکی موجود در انبار را نیز نشان می‌دهد. تعداد محصولات مشکی در قسمت "Color" نیز با توجه به شرایط جدید مجددا محاسبه می شود، فقط در بخش "دسته ها" چیزی تغییر نمی کند ... امیدوارم این مثال ها برای درک الگوریتم جستجوی معمولی کافی باشد.

حال بیایید تصور کنیم که چگونه می توان این را بر مبنای رابطه ای پیاده سازی کرد. هر گروه از معیارها، مانند دسته بندی و رنگ، به یک پرس و جو جداگانه نیاز دارند:

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. اگر الزام اکیدی از طرف کسب و کار برای نمایش تعداد کل نتایج یا نمایش شماره صفحات وجود ندارد و سیستم شما موتور جستجو ندارد، بهتر است این نکات را پیاده نکنید و گزینه شماره ۲ را در نظر بگیرید.
  3. اگر یک نیاز واضح برای جستجوی وجهی وجود دارد، شما دو گزینه بدون به خطر انداختن عملکرد دارید:
    • هر بار که معیار جستجو تغییر می کند، همه مقادیر را دوباره محاسبه نکنید.
    • از موتورهای جستجو مانند Solr، ElasticSearch، Sphinx و غیره استفاده کنید. اما باید درک کرد که نمی تواند جایگزینی برای پایگاه داده اصلی باشد و باید به عنوان مکمل ذخیره سازی اصلی برای حل مشکلات جستجو استفاده شود.
  4. همچنین، در مورد جستجوی وجهی، منطقی است که بازیابی صفحه نتایج جستجو و شمارش را به دو درخواست موازی تقسیم کنیم. شمارش مقادیر ممکن است بیشتر از به دست آوردن نتایج طول بکشد، در حالی که نتایج برای کاربر مهم تر است.
  5. اگر از پایگاه داده SQL برای جستجو استفاده می کنید، هرگونه تغییر کد مربوط به این بخش باید به خوبی از نظر عملکرد در مقدار مناسب داده (بیش از حجم در پایگاه داده زنده) آزمایش شود. همچنین توصیه می شود از نظارت بر زمان اجرای پرس و جو در تمام نمونه های پایگاه داده و به ویژه در مورد "زنده" استفاده شود. حتی اگر همه چیز با طرح‌های پرس و جو در مرحله توسعه خوب بود، با افزایش حجم داده‌ها، ممکن است وضعیت به طرز محسوسی تغییر کند.

منبع: www.habr.com

اضافه کردن نظر