PDA

View Full Version : مشکل سرعت لود کردن حجم بالای اطلاعات



neda azadi
پنج شنبه 17 اسفند 1385, 23:02 عصر
در شرکتی که من کار میکنم 2 برنامه حسابداری -انبارداری طراحی شده نسخه شبکه و تک
برای لود کردن اطلاعات فاکتورها با 200 رکورد در نسخه تک 1 ثانیه و در نسخه شبکه که پایگاه SQL SERVER دارد 30 ثانیه زمان صرف می شود . از نظر سخت افزار و سرعت شبکه مطمئن هستم که در سطح بالایی است . لطفاراهنمای کنید

whitehat
پنج شنبه 17 اسفند 1385, 23:32 عصر
برای افزایش کار آیی روش های متعددی وجود داره و بسته به سناریو شما می باشد ، زدن یک کوئری مناسب ، Index گذاری و پارتشن کردن داده ها و ... می تونه در افزایش کار آیی شما را کمک کند . بهتره در مورد جداول و نوع گزارش اطلاعات بیشتری بدهید(البته نسخه Sql خود را هم مشخص کنید)

AminSobati
جمعه 18 اسفند 1385, 19:50 عصر
باید دید روش کار در هر کدوم به چه صورته. من احتمال میدم شما برای این 200 رکورد، 200 بار یک SP رو Call میکنید که این Round Tripهای زیادی بین کلاینت و سرور در شبکه داره.

neda azadi
جمعه 18 اسفند 1385, 22:33 عصر
آقای ثباتی باید خدمتتون عرض کنم که من برای فاکتورها دو جدول یکی برای header و دیگری برای detail دارم . در هر دو نسخه هم یک حلقه while کاملا مشابه استفاده کردم . برای روتین ذخیره هم از SP استفاده کرده ام و لی برای لود کردن فقط locate و حلقه while . hdk ;hv vh f,sdgi ضعثقغ هم انجام دادم ولی باز هم نتیجه تغییری نکرد . فقط در پارادوکس از BDE و در SQL SERVER از ADODataset . از index گذاری هم استفاده کردم .
نکته دیگر اینکه مشکل من هم روی سرور و هم کلاینت هست .
از نسخه SQLDERVER 2000 استفاده می کنم .
جداول رو هم بیشتر از این امکان نداره که بشکنم . باز هم از شما و بقیه دوستان برنامه نویس که در این زمینه تجربیات خوبی دارند تقاضای همکاری را دارم .

AminSobati
شنبه 19 اسفند 1385, 08:31 صبح
دوست عزیزم شاید حدس من درست باشه و رفت و برگشتهای بین کلاینت و سرور برای اجرا کرد SP باعث کندی کار در شبکه باشه. من پیشنهاد میکنم تمام Detailها رو تبدیل به یک سند XML کنین و یکبار به SP ارسال کنین. نتیجه باید خیلی متفاوت باشه با روش قبلیتون

linux
شنبه 19 اسفند 1385, 10:59 صبح
آقای ثباتی باید خدمتتون عرض کنم که من برای فاکتورها دو جدول یکی برای header و دیگری برای detail دارم . در هر دو نسخه هم یک حلقه while کاملا مشابه استفاده کردم . برای روتین ذخیره هم از SP استفاده کرده ام و لی برای لود کردن فقط locate و حلقه while . hdk ;hv vh f,sdgi ضعثقغ هم انجام دادم ولی باز هم نتیجه تغییری نکرد . فقط در پارادوکس از BDE و در SQL SERVER از ADODataset . از index گذاری هم استفاده کردم .
نکته دیگر اینکه مشکل من هم روی سرور و هم کلاینت هست .
از نسخه SQLDERVER 2000 استفاده می کنم .
جداول رو هم بیشتر از این امکان نداره که بشکنم . باز هم از شما و بقیه دوستان برنامه نویس که در این زمینه تجربیات خوبی دارند تقاضای همکاری را دارم .
من هر چقدر فکر کردم نفهمیدم این while برای چی استفاده می شه!

neda azadi
شنبه 19 اسفند 1385, 21:03 عصر
من هر چقدر فکر کردم نفهمیدم این while برای چی استفاده می شه!

خیلی روشنه . ببینید هر فاکتوری یک سری کالا و یک شماره فاکتور دارد . شماره فاکتور کلید خارجی جدول detail است و حلقه while از شروع اولین کالای یک فاکتور تا انتهای آن ادامه دارد .

neda azadi
شنبه 19 اسفند 1385, 21:09 عصر
دوست عزیزم شاید حدس من درست باشه و رفت و برگشتهای بین کلاینت و سرور برای اجرا کرد SP باعث کندی کار در شبکه باشه. من پیشنهاد میکنم تمام Detailها رو تبدیل به یک سند XML کنین و یکبار به SP ارسال کنین. نتیجه باید خیلی متفاوت باشه با روش قبلیتون

من درست متوجه منظورتون نشدم . آخه من از SP فقط برای روتین ذخیره استفاده می کنم ولی مشکل سرعت من در لود کردن اطلاعاتییه که یک بار ذخیره شدند و حالا مثلا میخواهیم آنها را ویرایش کنیم . من نمی فهمم چه ربطی به sp داره به نظرم می آد که باید یک چیزی درباره QUERY من باشه . نمی شه یک طوری به query یک خاصیتی داد که سریعتر اجرا بشه .

AminSobati
شنبه 19 اسفند 1385, 21:31 عصر
شاید بشه خود Query رو به شکل بهینه تری نوشت و همچنین ممکنه ایندکسهای مناسب، گره گشا باشند. Queryی که فکر میکنید مشکل از اونه رو پست کنین لطفا

linux
یک شنبه 20 اسفند 1385, 00:31 صبح
یک مطلب را همزمان در دو پست دارید پیگری می کنید. بهتر هست که فقط اینجا ادامه بدهیم.
عرض شود که شما لقمه را دورسرتان می چرخانید. بخاطر همین انرژی که برای خوردن لقمه مصرف می کنید از انرژی که قرار از آن لقمه بگیرید بیشتر هست!
اگر با vb.net یا c# برنامه می نویسید می توانم کمک کنم.
فرض کن شما 1000 تا فاکتور داری هر فاکتور هم بطور متوسط 10 تا کالا میشه 10000 تا اصلا این عددی نیست.
من هنوز استفاده از while را اینجا نفهمیدم!
ببینید!
من نمی دانم از چه زبان برنامه نویسی استفاده می کنید. و الا یک مثال برای شما می فرستادم
لابد while را دربرنامه استفاده کردی وقتی یک رکورد را از جدول اصلی می خوانی بعد در یک حلقه یک به یک رکوردهای جدول زیرین را می خوانی و در دیتاگرید نمایش می دهی؟؟

linux
یک شنبه 20 اسفند 1385, 00:35 صبح
من درست متوجه منظورتون نشدم . آخه من از SP فقط برای روتین ذخیره استفاده می کنم ولی مشکل سرعت من در لود کردن اطلاعاتییه که یک بار ذخیره شدند و حالا مثلا میخواهیم آنها را ویرایش کنیم . من نمی فهمم چه ربطی به sp داره به نظرم می آد که باید یک چیزی درباره QUERY من باشه . نمی شه یک طوری به query یک خاصیتی داد که سریعتر اجرا بشه .
شما این while رادر کوئری استفاده کردی یا در برنامه خودت؟

neda azadi
یک شنبه 20 اسفند 1385, 13:59 عصر
شما این while رادر کوئری استفاده کردی یا در برنامه خودت؟


حق با شماست آقای linux من از بس برای جواب گرفتن عجله داشتم چند بار مطالب رو تکرار کردم . خدا رو شکر مشکلم حل شد . مشکلم روی close/open شدن زیاد جداولم بود که سرعت را می گرفت. متشکرم

neda azadi
یک شنبه 20 اسفند 1385, 14:04 عصر
شاید بشه خود Query رو به شکل بهینه تری نوشت و همچنین ممکنه ایندکسهای مناسب، گره گشا باشند. Queryی که فکر میکنید مشکل از اونه رو پست کنین لطفا



آقای ثباتی عزیز می شه sp من رو چک کنید ببینید چه وضعیتی از نظر بهینه بودن داره !!:لبخندساده:
CREATE PROCEDURE [insert_Forush_h]
(@HNo [char](6),
@HNoM [char](6),
@HDate [char](8),
@Kharidar [char](6),
@Remark [char](50),
@Takhfif [float],
@Anbar [char](2),
@TakhfifPer [float],
@Visitor [char](6),
@ArzType [char](3),
@ArzFrm [char](6),
@naghdi_flag [char](2),
@cashmab [float],
@cashhes [char](10),
@hascent [char](15),
@Tasvieh_Date [varchar](8),
@Type [Char](1),
@NHNo [char](6)output,
@Error [char](1)output)
as
begin transaction

if @Type='I'
begin
if @HNoM in (select HNo from Forush_h with(updlock))
begin
declare @NCode [char](6)
select @NCode=max(HNo) from Forush_h with(updlock)
SELECT @NCode=REPLACE(str(cast(@NCode as int)+1,6),' ','0')
if @NCode is null
select @NCode='000001'
end
else
begin
select @NCode=@HNoM
end

INSERT INTO Forush_h
([HNo],
[HDate],
[Kharidar],
[Remark],
[Takhfif],
[Anbar],
[TakhfifPer],
[Visitor],
[ArzType],
[ArzFrm],
[naghdi_flag],
[cashmab],
[cashhes],
[hascent],
[Tasvieh_Date])

VALUES
(@NCode,
@HDate,
@Kharidar,
@Remark,
@Takhfif,
@Anbar,
@TakhfifPer,
@Visitor,
@ArzType,
@ArzFrm,
@naghdi_flag,
@cashmab,
@cashhes,
@hascent,
@Tasvieh_Date)
select @NHNo=@NCode
end
if @Type='U'
begin
Update Forush_h set
[HDate]=@HDate,
[Kharidar]=@Kharidar,
[Remark]=@Remark,
[Takhfif]=@Takhfif,
[Anbar]=@Anbar,
[TakhfifPer]=@TakhfifPer,
[Visitor]=@Visitor,
[ArzType]=@ArzType,
[ArzFrm]=@ArzFrm,
[naghdi_flag]=@naghdi_flag,
[cashmab]=@cashmab,
[cashhes]=@cashhes,
[hascent]=@hascent,
[Tasvieh_Date]=@Tasvieh_Date
where
[HNo]=@HNo
select @NHNo=@HNo
end
IF @@ERROR <> 0
begin
select @Error='y'
rollback transaction
end
else
select @Error='n'
commit transaction
GO

AminSobati
یک شنبه 20 اسفند 1385, 21:57 عصر
نکته اول اینکه اگر روی فیلد hno ایندکس به این شکل ندارین، حتما بسازین:


create index _a_ix1 on Forush_h(HNo)

نکته دوم، علت استفاده از updlock موقع Select چیه؟ این عمل برای جلوگیری از Dead Lock کاربرد داره اما این نوع Dead Lockها زمانی پیش میاد که شما از Isolation Level بالاتر از Read Committed استفاده کرده باشین. من چنین چیزی در این SP نمیبینم، مگر اینکه در جای دیگه ای در Connection این کار رو انجام داده باشید. اگر از Read Committed میکنید، پس updlock رو حذف کنین. وجودش باعث میشه کاربر جدول رو Lock کنه و این SP چنانچه توسط کاربر دیگه ای همزمان صدا زده باشه، کار این دو تداخل میکنه و چون مرتبا همدیگه رو Lock میکنن، کار کندتر میشه.
البته من اطلاعی از سناریوی شما ندارم، شاید واقعا نیاز دارید فقط یک کاربر در هر لحظه بتونه این SP رو صدا بزنه، که در این صورت کند شدن SP طبیعی خواهد بود!

linux
یک شنبه 20 اسفند 1385, 22:29 عصر
من فکر می کنم شما کاری که راحت می توانید انجامش بدهید پیچیده کرده اید
میشه بگید با کدام زبان برنامه نویسی کار می کنید؟
کلی کد نوشتید که فقط شماره identity را بدست بیاورید! اگر این فیلد بصورت identity تعریف شده باشه احتیاج به این کارها نیست!
بعدش شما داری آپدیت می کنی یا اینزرت؟! شما اینجا به کاربر اصلا اطلاع نمی دهی که مثلا داره رکورد تکراری وارد می کنه! و چیزی که وارد می کنه بعنوان آپدیت داری ذخیره می کنی.بدون اطلاع کاربر فکر کن! سندی که قبلا زده شده کاربر شاید دسترسی اصلاح نداره با این کار می تواند سند را اصلاح کند.
پیشنهاد من
1- این sp را به دو sp آپدیت و اینزرت تبدیلش کن
2- یک فیلد جدید به نام id و بصورت identity تعریف کنید
3-توی این جدول حتما عناصری هستند که باید منحصر بفرد باشند مثلا شماره سریال برگ فروش که احتمالا همان hno هست شما 2 تا کار می توانید انجام بدهید
1- کاربر بدبخت تا آخرین خط اطلاعات را وارد کند بعد کنترل کنید
2- یا در همان ابتدا بعد از ورود این فیلد کنترل کنید که تکراری هست یا نه
در صورت تکراری بودن رکورد مورد نظر را لود کرده و به کاربر در صورت دسترسی به تغییرات اجازه دهید که اطلاعات مورد نظر را ویرایش کند

neda azadi
پنج شنبه 24 اسفند 1385, 22:29 عصر
اول از همه اینکه زبان مورد استفاده من دلفیه

سناریو اینه که :
هر فاکتور فروش یک شماره داره که همون hno هست . فرض کنید دو نفر همزمان برنامه را باز می کنند و فاکتور شماره 4 رو میبینند ( یکی بعد از آخرین فاکتور ذخیره شده ) و هر دو اطلاعات header و detail خودشون را وارد کنند و بخواهند با هم اطلاعات را ذخیره کنند . خب باید شماره فاکتور برای نفر دوم که دیرتر می رسه یک جوری بوجود بیاد یا نه ؟ نکته دوم اینه که ممکنه یک نفر دلش نخواد از اعداد معمول استفاده کنه مثلا تا فاکتور 100 ذخیره کرده حالا دلش می خواد از 200 به بعد شروع کنه . این ها همه دلایلی برای استفاده از اون قسمت تولید شماره است .
قسمت دوم سناریو اینه که روتین ذخیره و ویرایش برنامه ما یکیه به همین دلیل هم دو قسمت اینزرت و آپدیت داره .

قسمت بعدی اینه که آقای ثباتی عزیز وقتی دو نفر بخواهند دو فاکتور مجزا با کالاهای مثل هم بزنند و هر دو موجودی کالا رو توی انبار تغییر دهند باید هر کس زودتر می رسه کالا رو قفل کنه تا کارش تمام بشه و بعد نفر دوم روی نتایج نفر اول کارش رو ادامه بده وگرنه موجودی کالا که مهم ترین فاکتور در یک برنامه حسابداریه به هم میریزه ! به همین دلیل از updlock استفاده کردم . البته یک sp جانبی هم باز برای قفل کردن دارم

راستی من از این ایندکس اول روتینه ذخیره استفاده کردم باز هم نیاز هست که توی sp اون رو اضافه کنم .

با تشکر

AminSobati
پنج شنبه 24 اسفند 1385, 23:30 عصر
مطلب اول اینکه معمولا شماره فاکتور رو سیستم تولید میکنه و در اختیار کاربر قرار میده و در بعضی حالتها بعد از ثبت فاکتور، شماره اون توسط سیستم ارائه میشه ولی شاید اینها برای سناریوی شما عملی نباشه، لذا نمیتونم بگم حتما باید این کار رو انجام بدین.
مطلب دوم، اگر دو نفر همزمان از یک کالا بفروشند، و یکی زودتر از دیگری فاکتور رو Submit کنه، طبیعیه که کارش باید انجام بشه و کاربری که دیرتر عمل میکنه، بهش پیغام میدین که موجودی کافی نیست. شما نباید انبار رو در طول زمانی که کسی فاکتور میزنه قفل کنین. شاید کاربر رفت ناهار بخوره! در طول این مدت کسی نباید اون کالا رو بفروشه؟
مطلب سوم، ایندکس یکبار ساخته میشه.