PDA

View Full Version : حرفه ای: افزایش سرعت پیمایش دیتاست ADO



alidehban
دوشنبه 20 آذر 1396, 13:33 عصر
با درود ...
من یک بخشی در سیستم امکان Export دارم که بنا بر درخواست های چندین ساله امکانات خاص زیادی داره. یک ازونها این هست که بطور مثال در خروجی گرفتن برای اکسل کاربر میتونه یک کوئری رو که دیتاست مربوط به اون طبق کوئری مثلاً 5 تا فیلد داره رو بیاد یک نگاشت (Map ) ایجاد میکنه و لا به لای فیلدهای Select شده فیلدهای دلخواه ( تغییر ردیف و اولویت نمایش فیلد ، متن دلخواه ، Delimiter ، فرمول اکسل و غیره ...) اضافه میکنه. یعنی خروجی نهایی ممکنه با اونچه که در Select بوده متفاوت باشه و در RunTime باید خروجی رو اصلاح کرد و همزمان در فایل (بطور مثال اکسل) نوشت ، برای پیاده سازی این مورد با توجه به اینکه همه ی موارد خواسته شده از کاربرا رو نمیشد در SQL پیاده کرد مجبور شدم کوئری رو اجرا کنم وموقع نوشتن در فایل تغییرات رو انجام بدم .
در حلقه ای که از دیتای اصلیِ برگشته از کوئری دارم برای هر رکورد دیتا باید کل جدول نگاشت بررسی و اعمال بشه و دلیلش هم این هست که در نوشتن در خروجی (بطور مثال اکسل ) خروجی رکورد به رکورد درج میشه که Map رو در یک لیست نگهداشتم و این بخش بسیار سریع عمل میکنه اما پیمایش خود دیتاستِ شامل دیتا کند هست.

سوالم این هست که برای پیمایش و Pars کردن رکورد به رکورد دیتاست چه روشی سریع ترین و به اصطلاح best practice هست؟
چه راه حلی وجود داره که سرعت رو افزایش بدم؟

از Recordset به جای دیتاست استفاده کردم و DisableControls هم کردم اما اینا کافی نیست و اگر Pars رکورد به رکورد اتفاق نیفته بطور مثال برای 140000 رکورد کسری از ثانیه Export میگیره ولی با بررسی رکور به رکورد میشه 25 دقیقه...!
در صورتیکه هر بررسی و در واقع هر دور حلقه ی اصلی هم در کسری از میلی ثانیه داره اتفاق میفته اما کل کار بشدت کند میشه...

پیشاپیش سپاس...

یوسف زالی
دوشنبه 20 آذر 1396, 15:38 عصر
سلام.
روی دیتاست رویدادهایی مثل OnCalc یا AfterScroll دارید؟
روی گرید رویدادی دارید؟
فیلد لوکاپ روی دیتاست دارید؟
روی فیلدهاتون GetText دارید؟
فیلد بلاب دارید؟
این ها رو جواب بدید تا بعد ..

alidehban
دوشنبه 20 آذر 1396, 17:02 عصر
روی دیتاست رویدادهایی مثل OnCalc یا AfterScroll دارید؟
خیر...

روی گرید رویدادی دارید؟
دیتاست فقط Data Container هست و به گرید متصب نیست.

فیلد لوکاپ روی دیتاست دارید؟
خیر

روی فیلدهاتون GetText دارید؟
خیر...

فیلد بلاب دارید؟
خیر... تمام فیلدها String هستند.

نکته : تنها فانکشنی که در چند جای عملیات (در هر loop حلقه 2 بار یکبار برای چک Nil بودن و یکبار هم برای چک دیتاتایپ فیلد مذکور) اتفاق میفته FindField هست که اونم واقعاً زمانی نمیبره وقتی trace میکنم.

یوسف زالی
سه شنبه 21 آذر 1396, 21:53 عصر
CursorLocation رو سمت سرور و CursorType رو OpenForwardOnly بگذارید. دیتاست رو هم ReadOnly کنید.
به هیچ وجه هم از RecNo استفاده نکنید.
اینها رو تست کنید بگید.
بهتره FindField رو هم بهینه سازی کنید، چون خودش یک لوپ داره، و تعدادش داخل حلقه شما ضرب می شه ..

یوسف زالی
چهارشنبه 22 آذر 1396, 12:15 عصر
راستی فقط روی پیمایش مشکل دارید یا اوپن شدن هم مدنظره؟
موارد بالا تاثیری داشت؟

alidehban
شنبه 25 آذر 1396, 08:33 صبح
CursorLocation رو سمت سرور و CursorType رو OpenForwardOnly بگذارید. دیتاست رو هم ReadOnly کنید.
به هیچ وجه هم از RecNo استفاده نکنید.
اینها رو تست کنید بگید.

ممنون از شما بابت توضیحات و وقتی که گذاشتید.
من موارد بالا رو با دقت بررسی کردم و تست های مختلفی زدم اما تفاوت سرعت چشمگیری اتفاق نیفتاد.


بهتره FindField رو هم بهینه سازی کنید، چون خودش یک لوپ داره، و تعدادش داخل حلقه شما ضرب می شه ..
اما این مورد موثر بود و تا حدود 30 درصد میتونم بگم ارتقا ایجاد شد. اصلاً به لوپ داخل این فانکشن دقت نمیکردم.
بازهم ممنون و سپاسگزار...

alidehban
شنبه 25 آذر 1396, 09:05 صبح
راستی فقط روی پیمایش مشکل دارید یا اوپن شدن هم مدنظره؟
موارد بالا تاثیری داشت؟

مشکل فقط در پیمایش هست البته پیمایش همراه با درج در اکسل.
واقعیت این هست که تمام کندی مربوط به ADO نیست بلکه مقدار زیادی OLE مقصر ماجراست و با توجه به اینکه هر تابع OLE که شما استفاده کنید در لیست پرشمار توابعی که بصورت String هم جستجو میشن ابتدا باید پیدا بشه و بعد اجرا بشه باعث میشه ذاتاً کند باشه...
بررسی فراوان من رو به این نتیجه رسوند که بیشتر باید روی راه حلی برای بهینه استفاده کردن از OLE تمرکز کنم یا در صورت امکان استفاده نکنم.
البته در این مورد خاص مجبورم از OLE استفاده کنم چون تغییرات لازم رو در خروجی ، دستی ایجاد میکنم و تنها کاری که تونستم برای افزایش سرعت انجام بدم
این بود که کد رو جوری بنویسم که از تعداد فراخوانی های توابع Ole کم بشود و همزمان به جای نوشتن سلولی از نوشتن بصورت Range باید استفاده کرد. این دو و بهینه سازی های دیگر مربوط به دیتاست و باقی کد ها
سرعت کار رو به مقدار 40 درصد حدوداً ارتقا داد اما باز هم نسبت به روش غیر OLE بسیار کند و آزار دهنده هست.

نتیجه ی اخلاقی : تا جایی که میشه از OLE استفاده نکنید!

یوسف زالی
شنبه 25 آذر 1396, 10:06 صبح
اگر به ازای هر یک ردیف یک درج انجام می دید، به نظرم می تونید دسته ای این کار رو کنید، مثلا صدتا صدتا درج انجام بدید و تعداد تراکنش ها رو هم کمتر کنید.
موفق باشید.

ihpled
چهارشنبه 17 بهمن 1397, 14:31 عصر
با درود ...
از Recordset به جای دیتاست استفاده کردم

آیا رکوردست همه کارهای دیتاست انجام میده و استفاده از این کار مفید هست؟

alidehban
دوشنبه 22 بهمن 1397, 16:57 عصر
با درود...
- استفاده از ركوردست موثر هست در performance اما نه هميشه بستگي به شرايط داره، مثلا وقتي كه شما در كوئري چندين Recordset برميگردونيد (چند Select داريد) يكي از حالات هست كه تفاوت چشمگير با Dataset داره، بايد تست كنيد ، نسخه اي نيست كه بشه پيچيد براي تمام حالات .
- همه ي كاراهاي ديتاست رو انجام ميده منتها نحوه ي كدنويسيش سخت تر و پر دردسرتر خواهد بود ، بعضي امكانات جالب هم وجود داره كه خيلي ماها ازش استفاده نميكنيم بطور مثال ميتونيد كانكشن ركورد ست رو قطع كنيد و بصورت آفلاين كار كنيد يا ميشه ديتاش رو در يك فايل ذخيره كرد و بدون يك ديتابيس سرور آنلاين مثل SQL صرفاً با فايل كار كنيد البته براي دمو و كارهاي كوچك مفيده ...
به هر حال من هم فقط براي پيمايش ازش استفاده كردم و پيشنهاد نميكنم به جاي ديتاست استفاده كنيد چون كلي helper آماده رو از دست ميديد.
راستي اگر مشكل فقط سرعت پيمايش باشه يك راه حل ديگه هم اين هست كه ديتاست بازگشتي رو در يك ليست يا شايد آبجكت ليست يا آرايه نگهداري كنيد و اون رو با حداكثر سرعت پيمايش كنيد.