PDA

View Full Version : حرفه ای: روشی بهینه تر و سریع تر برای این صفحه بندی



علیرضا حسن زاده
شنبه 19 آذر 1390, 19:26 عصر
سلام من از کد زیر تو برنامم برای صفحه بندی اطلاعات استفاده می کنم تاحدودی هم سرعت افزایش پیدا کرده ولی هنوز کنده کسی روش بهتری سراغ داره؟

DatabindingSource.DataSource =
SnData.DataContext.SndSearchViews.Where(
t =>
(t.FullName.Contains(fullname) || t.FullName.Contains(fullname2)) &&
(t.InDate >= fromdate &&
t.InDate <= todate) &&
(t.SaveDate >= fromdate &&
t.SaveDate <= todate)).OrderBy(t => t.SndId).Skip(_skip).Take(10);
متغییر skip_ هر بار 10 تا اضافه یا کم میشه تا کاربر بتونه به صفحه بعدی یا قبلی منتقل بشه
توجه: SndSearchViews هم یک View تو Sqlserver هست

mehdi.mousavi
شنبه 19 آذر 1390, 20:17 عصر
سلام.
بر اساس نحوه توزیع داده ها و چگونگی انتخاب بازه های زمانی، اگر شرط چک کردن بازه های زمانی رو در ابتدا قرار بدید، شاید سرعت انجام Query به طرز چشمگیری تغییر کنه. در حالت کلی کدی که نوشته اید ایرادی نداره و یک SQL Statement سر راست تولید میکنه. تنها بخشی که میشه روی اون تمرکز کرد، به گمانم همون مقایسه Fullname هستش. اگر با جابجایی شرط به نتیجه نرسیدید، می تونید با فعال کردن FTS در SQL Server کارایی اجرای کد فوق رو افزایش بدید. برای آشنایی با چگونگی آدرس کردن CONTAINS، CONTAINSTABLE و ... در LINQ to SQL نیز، می تونید به این آدرس (http://sqlblogcasts.com/blogs/simons/archive/2008/12/18/LINQ-to-SQL---Enabling-Fulltext-searching.aspx) رجوع کنید.

موفق باشید.

علیرضا حسن زاده
شنبه 19 آذر 1390, 22:10 عصر
با تشکر از پاسخ شما
اما فکر نمی کنم باجابه جایی شرط تغییری حاصل شود چون از این کد برای حالتی استفاده میکنم که ممکنه کاربر تاریخ رو وارد کنه یا وارد نکنه و همچنین fullname رو ممکنه وارد نکنه یعنی همه اختیاری هستن
مساله که به ذهنم اومد اینکه برای هر با اجرای دستور تمام رکورد ها واکشی میشن بعد سورت میشن بعد هم جدا می شن و به کاربر نمایش داده میشن(البته اکثر این کارا توسط SQLServer انجام میشه) و برای هر با هم که کاربر کلید قبلی یا بعدی رو کلیک کنه این کار مجدد انجام میشه View هم از چندین جدول اطلاعات رو میگره اگه بتونم اطلاعات رو در سمت SQLServer یا Linq به روشی محدود کنم که هر با داده زیادی وکشی و سورت نشه سرعت اجرا خیلی بالا میره چون تعداد رکوردها زیادن(حدود 100000تا)
البته FTS(اگه منظورتون همون Full Text searching نباشه) رو نمی دونم چیه سعی مکنم دربارش مطالعه کنم

zarrinnegar
شنبه 19 آذر 1390, 23:01 عصر
من از این راه ابتکاری خودم استفاده میکنم و برای میلیونها رکورد میشه استفاده کرد


این هم خلاصه



create PROCEDURE [dbo].[sp_PagedItem]
(
@Page int,

@RecsPerPage int
)
AS
CREATE
TABLE #TempItems

(



ID intIDENTITY,

,
,
,
)
INSERT
INTO #TempItems
(,


,


)

SELECT,,FROM myTable

DECLARE
FirstRec int, @LastRec int

SELECT
@FirstRec =(@Page - 1)* @RecsPerPage

SELECT
@LastRec =(@Page * @RecsPerPage + 1)

SELECT
*,

MoreRecords
=
(


SELECTCOUNT(*)

FROM #TempItems TI

WHERE TI.ID >= @LastRec

)

FROM
#TempItems

WHERE
ID > @FirstRec AND ID < @LastRec

mehdi.mousavi
شنبه 19 آذر 1390, 23:30 عصر
با تشکر از پاسخ شما اما فکر نمی کنم باجابه جایی شرط تغییری حاصل شود چون از این کد برای حالتی استفاده میکنم که ممکنه کاربر تاریخ رو وارد کنه یا وارد نکنه و همچنین fullname رو ممکنه وارد نکنه یعنی همه اختیاری هستن مساله که به ذهنم اومد اینکه برای هر با اجرای دستور تمام رکورد ها واکشی میشن بعد سورت میشن بعد هم جدا می شن و به کاربر نمایش داده میشن(البته اکثر این کارا توسط SQLServer انجام میشه) و برای هر با هم که کاربر کلید قبلی یا بعدی رو کلیک کنه این کار مجدد انجام میشه View هم از چندین جدول اطلاعات رو میگره اگه بتونم اطلاعات رو در سمت SQLServer یا Linq به روشی محدود کنم که هر با داده زیادی وکشی و سورت نشه سرعت اجرا خیلی بالا میره چون تعداد رکوردها زیادن(حدود 100000تا) البته FTS(اگه منظورتون همون Full Text searching نباشه) رو نمی دونم چیه سعی مکنم دربارش مطالعه کنم

سلام مجدد.
پس از اونجاییکه پارامترها اختیاری هستن، جابجایی WHERE CLAUSE ها نمیتونه کمکی کنه. اما اینکه میگید کلیه رکوردها واکشی میشن، سپس مرتب شده و به کاربر نمایش داده میشن صحت نداره. کدی که شما نوشته اید، Query ی Efficient ای تولید میکنه. کد زیر رو در نظر بگیرید:

var addrs = db.Addresses.Where(a => a.StateProvince.Contains(state) || a.StateProvince.Contains(state))
.OrderBy(t => t.addressID)
.Skip(3).Take(10).ToList();


این کد، SQL Statement ای به شکل زیر تولید میکنه:


SELECT [t1].[addressID], [t1].[Street1]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[addressID]) AS [ROW_NUMBER], [t0].[addressID], [t0].[Street1]
FROM [dbo].[Address] AS [t0]
WHERE ([t0].[StateProvince] LIKE @p0) OR ([t0].[StateProvince] LIKE @p1)
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p2 + 1 AND @p2 + @p3
ORDER BY [t1].[ROW_NUMBER]


که در اون @p2 و @p3 پارامترهای مورد نظر ما برای Paging هستش (همون 3 و 10 در کد فوق) که باعث میشه Result Set مورد نظر ما سمت سرور انتخاب بشه و فقط 10 مورد اخیر به Client بازگردونده بشه. برای اینکه کد فوق سمت سرور سریع اجرا بشه، باید مطمئن بشید که Index های مورد نظر روی ستون DateTime وجود داره. اما اگر FTS رو روی SQL Server فعال کنید، SQL Server بر اساس Index های مخصوصی که برای Free Text Search روی ستون مورد نظر میسازه استفاده می کنه و Performance بطرز معجزه آسایی بالا میره. به نظر من، در مرحله اول، دستور تولید شده LINQ 2 SQL رو در SQL Profiler بررسی کنید تا ببینید گلوگاه کجاست، سپس اقدام به رفع اون کنید.

موفق باشید.

علیرضا حسن زاده
یک شنبه 20 آذر 1390, 06:31 صبح
یه چیزی خیلی وقته ذهنمو مشغول کرده این Row_Number هست که تو Qurey تولید شده موجود داره آیا راهی هست که بتونیم اونو تو برنامه هم داشته باشیم و از مقدارش استفاده کنیم بالاخره تو Result set دستور وجود داره دیگه؟