PDA

View Full Version : سوال: افزایش سرعت کوئری



hamid_14
چهارشنبه 26 شهریور 1393, 14:15 عصر
سلام
من از کوئری زیر استفاده کردم و 18193 رکورد در 6 دقیقه و 48 ثانیه لود میکنه فیلد fdate هم ایندکس کردم فقط چند ثانیه کمتر شد کلیه فیلد های اضافی هم حذف کردم نمی دونم این سرعت درسته یا راهی هست که سریع تر بشه.بانکم sqlite هست لطفا اگه راهی داره راهنمائی کنید خیلی گیرم.


SELECT t1.description,t1.fdate, t1.id,t1.dp,t1.cp,(select IFNULL(SUM(Cp),0) - IFNULL(SUM(Dp),0) from [TBL_TRANSACTIONS] t2 where (t2.fdate < t1.fdate AND t1.acc=t2.acc) or (t2.fdate = t1.fdate and t2.ID <= t1.ID AND t1.acc=t2.acc) ) RE, (Select TRIM(PDS) From TBL3 Where ID = t1.PID) as NPDS,
(Case R_TAG
WHEN '1' THEN
(SELECT NAME FROM TBL1 WHERE ID = CID)
WHEN '2' THEN
(SELECT 'To:'||NAME FROM TBL2 WHERE ID = CID)
WHEN '3' THEN
(SELECT 'From:'||NAME FROM TBL2 WHERE ID = CID)
END) as TName
FROM [TBL_TRANSACTIONS] t1
Where (t1.sdate>=:insdate) AND (t1.sdate<=:inedate)
AND (t1.ACC=:inaone) AND (R_TAG <> 0)
ORDER BY t1.fdate

یوسف زالی
چهارشنبه 26 شهریور 1393, 16:21 عصر
سلام.
به نظرم ساب سلکت اول مشکل سرعت داره. اگر لازمه با join پیادش کنید.


IFNULL(SUM(Cp),0) - IFNULL(SUM(Dp),0)

بهتره که سام بیرون نوشته بشه:


IFNULL(SUM(Cp-Dp),0)

منطقا با این تعداد رکورد باید زیر 10 ثانیه بتونید کوئری بگیرید. (البته به طور خیلی مجمل، وگرنه سرعت به آیتم های زیادی بستگی داره)
این رو هم اضافه کنم که این کار رو می تونید در UI هم انجام بدید، تفاوتش زمین تا آسمونه. مثلا برای همین مانده گیری، قول می دم از سرعتش لذت ببرید.
بهتره این کار سمت برنامه انحام بشه و در قالب یک فیلد محاسباتی، یا در قالب یک ClientDataSet گنجونده بشه.
نمونه این کار رو قبلا بارها انجام دادم و هربار از سرعتش استفاده زیادی کردم.
یکمی برنامه نویسی تون زیاد می شه، ولی می ارزه.

hamid_14
چهارشنبه 26 شهریور 1393, 18:16 عصر
بله دقیقا مشکل از ساب سلکت اول که مربوط به running totals می شه من کد رو تغییر دادم و از join استفاده کردم(اگه درست استفاده کرده باشم) ولی هیچ تغییری تو سرعت نداشت.در مورد فیلد محاسباتی هم قبلا اگه اشتباه نکنم مشکل داشت مثلا با حرکت اسکرول dbgrid محاسبات بهم می ریخت.


SELECT t1.description,t1.fdate, t1.id,t1.dp,t1.cp,(IFNULL(SUM(t2.Cp-t2.Dp),0)) RE, (Select TRIM(PDS) From TBL3 Where ID = t1.PID) as NPDS,
(Case t1.R_TAG
WHEN '1' THEN
(SELECT NAME FROM TBL1 WHERE ID = t1.CID)
WHEN '2' THEN
(SELECT 'To:'||NAME FROM TBL2 WHERE ID = t1.CID)
WHEN '3' THEN
(SELECT 'From:'||NAME FROM TBL2 WHERE ID = t1.CID)
END) as TName
FROM [TBL_TRANSACTIONS] t1 INNER Join [TBL_TRANSACTIONS] t2 ON (t2.fdate < t1.fdate AND t1.acc=t2.acc) or (t2.fdate = t1.fdate and t2.ID <= t1.ID AND t1.acc=t2.acc)
Where (t1.sdate>=:insdate) AND (t1.sdate<=:inedate)
AND (t1.ACC=:inaone) AND (t1.R_TAG <> 0)

ORDER BY t1.fdate

یوسف زالی
چهارشنبه 26 شهریور 1393, 18:55 عصر
روش آخر رو به کار ببرید: استفاده از MemoryDS ها.
یکی از مموری دیتاست ها همین کلاینت دیتاسته.
محاسبات رو در اون اینسرت کنید.

hamid_14
شنبه 29 شهریور 1393, 01:43 صبح
calculate فیلد سرعت خیلی بالائی داره ولی با dbgrid مشکل داره آیا میشه کد زیر در کوئری انجام داد.نحوه استفاده از متغیر در sqlite چطوری هست؟


var i : Real;begin
i := i + (query1.Fieldbyname('d').asfloat - query1.Fieldbyname('c').asfloat);
Value := i;

یوسف زالی
شنبه 29 شهریور 1393, 01:45 صبح
بهتون که گفتم از روش آخر استفاده کنید، خالی کردن دیتاست روی مموری دیتاست و محاسبه فیلد هایی که لازم دارید.
روشی که دنبالش هستید استفاده از کرسر (بر فرض ساپورت) هست که از خود join و subselect بسیار بدتره.

hamid_14
شنبه 29 شهریور 1393, 11:01 صبح
درمورد کرسر که ساپورت نمی کنه اما درمورد روش شما من clientdataset به query متصل کردم ولی نمی دونم چطور و کجا محاسبات انجام بدم و insert کنم تو clientdataset همچنین کی حافظه باید خالی بشه.لطفا اگه امکان داره بیشتر راهنمائی کنید یا اگه وقت ندارید keywords هایی که میشه باهاشون تو اینترنت جستجو کرد معرفی کنید.تشکر

یوسف زالی
شنبه 29 شهریور 1393, 11:14 صبح
نباید کلاینت رو مستقیم وصل کنید. خودتون به طور دستی اطلاعات رو از ADO در CDS تخلیه کنید. ضمن این کار فیلد هایی رو که می خواهید هم محاسبه کرده و در قالب فیلد دیتا در CDS لحاظ کنید.
اگر DisableControls کنید زمان انجام این تخلیه خیلی نمی شه، برای 20 هزار رکورد شاید دو ثانیه.