PDA

View Full Version : سوال: مقایسه اطلاعات دیتابیس با سرعت بالاتر



group45
یک شنبه 04 فروردین 1392, 21:32 عصر
با سلام و تبریک سال نو
من اطلاعات سه فیلد ار دیتابیس رو سلکت کردم و تو دیتا ریدر ریختم. نوعشون اینتجره و اعدادی بین 1 تا مثلا ده هزار هستن ولی شاید چند تا عدد تو دیتابیس نباشه میخوام این اعداد رو پیدا کنم و تو لیست باکس نشون بدم
من این کار رو کردم با دو روش ولی روشی میخوام که سرعت بالاتری داشته باشه. چون روشام واسه هشت هزار تا 20 ثانیه طول میکشن.
روش اول:تو یه حلقه فور از 1 تا آخرین عدد تک تک اعداد حلقه رو تو دیتابیس جستجو کردم و اگه نبود تو لیست باکس ریختمش. -- زمان زیادی کانکشن باز می مونه.
روش دوم: کله سه فیلد رو تو دیتاریدر ریختم و اعداد از 1 تا آخر رو تو لیست باکس ریختم و هر عددی که از دیتاریدر می خوندم از لیست بر میداشتم.

آیا راه سریعتری هست؟

Mahmoud.Afrad
یک شنبه 04 فروردین 1392, 22:46 عصر
اگر با Linq کار میکنی به اینصورت میتونی انجام بدی:

// all range
IEnumerable<int> allNumber = Enumerable.Range(0, 8000).ToList();
// stored numbers in database
List<int> storedNumbers = context.tbls.Select(i => i.num).Cast<int>().ToList();
// number in all range but not in stored numbers
List<int> diffNumbers = allNumber.Except(storedNumbers).ToList();


اگر با ado.net کار میکنی : همه شماره های ثبت شده رو سلکت کن و در برنامه از مجموعه تمام اعداد اون رنج کنار بزار مثل مثال بالا.

ali_habibi1384
دوشنبه 05 فروردین 1392, 00:51 صبح
خب پيشنهاد من دقيقا روش برعكس روش اول شماست:
ابتدا كليه اعداد رو از 1 تا 8000 توي ليست باكس ميذاري حالا يكبار از ديتا بيس كل اعداد رو سلكت ميكني و در حلقه فور دوم اطلاعات ديتا تيبل رو يكي يكي ميري جلو حالا هر عددي رو كه پيدا كردي از ليست حذف ميكني . درنهايت اعدادي كه ميمونه همونايي هست كه توي جدولت موجود نبوده.
بيشتر وقت شما در روش اول واسه فيلتر كردن و خوندن و اتصال به ديتا بيس هدر ميشه حداقل در اين روش فقط يكبار همه اطلاعات رو ميخوني و سرورت هم نميخوابه.
تست كن روش منو ببين جواب ميگيري، نتيجه شو بگو
واسه مديريت اعداد تكراري مثلا اگر 5 تا عدد 3 وجود داشته باشه ميتوني سلكتي رو كه از ديتابيس ميگيري با Distinct بگيري كه تكراريهاش حذف بشه تا حلقه فور دومت كمتر بشه

veniz2008
دوشنبه 05 فروردین 1392, 02:18 صبح
سلام.
پیشنهاد من اینه که تمام عملیات رو سمت sql انجام بدید چون به نظر میرسه سرعت فیلتر کردن سمت sql بیشتر از سرعت فیلتر در سمت سی شارپ باشه و همچنین نیازی به لود کردن همه داده ها و آوردشون به محیط سی شارپ و استفاده از دیتاتیبل و مصرف RAM بخاطر 10 هزار رکورد و ... نیست و فقط خیلی راحت نتیجه نهایی رو برگشت می دید.
برای این کار نیازه که یک جدول موقت که شامل اعداد 1 تا 10000 میشه بسازید و بعد از دستور NOT IN استفاده کنید. من در سیستم خودم کد رو اجرا کردم و نتیجه کوئری در سمت sql در کسری از ثانیه اجرا شد و به نظرم سریعتر از این باشه که سمت سی شارپ فیلتر رو انجام بدید. کد زیر رو ببینید :

declare @count int
CREATE TABLE #TEMPTable
(
id int
)
set @count = 1
while @count <= 10000
begin
insert into #TEMPTable(id) values(@count)
set @count = @count + 1
end
select id from #TEMPTable where id NOT IN(select KalaID from TblKala)
موفق باشید.

group45
سه شنبه 06 فروردین 1392, 01:27 صبح
سلام.
پیشنهاد من اینه که تمام عملیات رو سمت sql انجام بدید چون به نظر میرسه سرعت فیلتر کردن سمت sql بیشتر از سرعت فیلتر در سمت سی شارپ باشه و همچنین نیازی به لود کردن همه داده ها و آوردشون به محیط سی شارپ و استفاده از دیتاتیبل و مصرف RAM بخاطر 10 هزار رکورد و ... نیست و فقط خیلی راحت نتیجه نهایی رو برگشت می دید.
برای این کار نیازه که یک جدول موقت که شامل اعداد 1 تا 10000 میشه بسازید و بعد از دستور NOT IN استفاده کنید. من در سیستم خودم کد رو اجرا کردم و نتیجه کوئری در سمت sql در کسری از ثانیه اجرا شد و به نظرم سریعتر از این باشه که سمت سی شارپ فیلتر رو انجام بدید. کد زیر رو ببینید :

declare @count int
CREATE TABLE #TEMPTable
(
id int
)
set @count = 1
while @count <= 10000
begin
insert into #TEMPTable(id) values(@count)
set @count = @count + 1
end
select id from #TEMPTable where id NOT IN(select KalaID from TblKala)
موفق باشید.


ممنون از شما.تو خط آخر که داره انتخاب میکنه تو انتخاب دوم من باید سه تا فیلد رو بخونم. چطور باید سه فیلد که همشون عددصحیح هستن رو بریزم تو همون id ؟؟؟؟؟؟؟؟؟؟؟؟؟؟

veniz2008
سه شنبه 06 فروردین 1392, 02:23 صبح
ممنون از شما.تو خط آخر که داره انتخاب میکنه تو انتخاب دوم من باید سه تا فیلد رو بخونم. چطور باید سه فیلد که همشون عددصحیح هستن رو بریزم تو همون id ؟؟؟؟؟؟؟؟؟؟؟؟؟؟
اگر منظورتون اینه که به هر سه فیلد جدول نیاز دارید ولی اونایی که id شون در جدول دیگه نیست رو میخواید داشته باشید میتونید بصورت زیر بنویسید:

declare @count int
CREATE TABLE #TEMPTable
(
id int
)
set @count = 1
while @count <= 10000
begin
insert into #TEMPTable(id) values(@count)
set @count = @count + 1
end
select * from TblKala TK where NOT EXISTS(select id from #TEMPTable T where TK.KalaID = T.id)
بصورت زیر و با همون NOT IN هم میشه پیاده سازی کرد (نتیجه با کد بالا یکسان هستش) :

declare @count int
CREATE TABLE #TEMPTable
(
id int
)
set @count = 1
while @count <= 10000
begin
insert into #TEMPTable(id) values(@count)
set @count = @count + 1
end
select * from TblKala where KalaID NOT IN(select id from #TEMPTable)
اگر منظورتون چیز دیگه ای هست، بیشتر توضیح بدید.(اگر تونستید یه عکس هم از جدول هاتون بذارید بهتر میشه راهنمایی کرد).

group45
سه شنبه 06 فروردین 1392, 09:55 صبح
ممنون از توجهتون
منظورم اینه که: در خط select id from #TEMPTable where id NOT IN(select KalaID from TblKala) بجای KalaID سه تا فیلد باید سلکت شن

سه تا فیلد رو چطور میشه ریخت تو یه فیلد جدید؟؟؟؟؟؟؟؟

veniz2008
سه شنبه 06 فروردین 1392, 11:55 صبح
ممنون از توجهتون
منظورم اینه که: در خط select id from #TEMPTable where id NOT IN(select KalaID from TblKala) بجای KalaID سه تا فیلد باید سلکت شن

سه تا فیلد رو چطور میشه ریخت تو یه فیلد جدید؟؟؟؟؟؟؟؟
در عبارت select بالا، اولین select تعیین کننده تعداد فیلدهای انتخابی هستش. جدول موقت TEMPTable# فقط یک فیلد با نام id داره بنابراین نمیتونه خروجی داشته باشه که سه فیلد داره. واسه همین بود که در پست 6 کوئری رو تغییر دادم و در واقع جای دو جدول با هم عوض شده. در جدول TblKala، من چندین فیلد دارم که یکیش KalaID هست و با id از جدول TEMPTable# مقایسه میشه. اگر به پست 6 دقت کنید می بینید که از * استفاده کردم تا همه فیلدها نمایش داده بشن (شما میتونی اگه همه فیلدها رو نمیخوای، نام فیلدهای مورد نظرتون رو تایپ کنید).
کوئری پست 6، رکوردهایی رو از جدول کالا برمیگردونه که در جدول TEMPTable# وجود نداره(در واقع آی دی کالا با آی دی جدول موقت یکسان نباشه).

group45
سه شنبه 06 فروردین 1392, 12:53 عصر
با تشکر از همه شما دوستان
مشکل رو حل کردم
15000 عملیات تحت دیتابیس در 3 ثانیه که قبلا بیشتر از 60 ثانیه میشد. کلی حال کردم :کف:

veniz2008
سه شنبه 06 فروردین 1392, 13:13 عصر
با تشکر از همه شما دوستان
مشکل رو حل کردم
15000 عملیات تحت دیتابیس در 3 ثانیه که قبلا بیشتر از 60 ثانیه میشد. کلی حال کردم :کف:
دوستان لطف کنند وقتی یه تاپیک به نتیجه میرسه راه حل بهتر رو هم بگن تا در آینده افرادی که میخوان از اینچنین تاپیک هایی استفاده کنن سردرگم نشن.
اینکه از کدوم روش استفاده کردید (Exists یا NOT IN ) یا از روش هایی که بقیه دوستان توضیح دادن و کلا هر نکته مفیدی که فکر می کنید نیازه ذکر بشه رو بگید.چون این تاپیک به آرشیو مبره و بعدا شاید کسی دیگه به ما دسترسی نداشته باشه که این سوالات رو بپرسه.
موفق باشید.

FastCode
سه شنبه 06 فروردین 1392, 16:29 عصر
من هیچ موقع اینقدر بد طراحی نکردم که مجبور بشم چنین کاری انجام بدم.
ولی اگر مجبور بشم در سمت کلاینت از SortedSet استفاده میکنم.
و در سمت سرور
select (select 1 + ISNULL(Max(T2.ID),0) from MyTable as T2 where T2.ID < MyTable.ID) as LBound, ID - 1 as UBound from MyTable where not Exists(select * from MyTable as T2 where T2.ID = MyTable.ID - 1) and ID <> 1

اگر بتونید اطلاعات رو قبلا در سمت کلاینت داشته باشید سرعت SortedSet بسیار بیشتره.

group45
سه شنبه 06 فروردین 1392, 16:53 عصر
دوستان لطف کنند وقتی یه تاپیک به نتیجه میرسه راه حل بهتر رو هم بگن تا در آینده افرادی که میخوان از اینچنین تاپیک هایی استفاده کنن سردرگم نشن.
اینکه از کدوم روش استفاده کردید (Exists یا NOT IN ) یا از روش هایی که بقیه دوستان توضیح دادن و کلا هر نکته مفیدی که فکر می کنید نیازه ذکر بشه رو بگید.چون این تاپیک به آرشیو مبره و بعدا شاید کسی دیگه به ما دسترسی نداشته باشه که این سوالات رو بپرسه.
موفق باشید.

ابتدا یه تیبل با یه فیلد اینتجر ایجاد کردم بعد تک تک اعضای هر سه فیلد رو تو فیلد این تیبل ریختم بعد یه تیبل دیگه با یه فیلد اینتجر ایجاد کردم و با دستورات خود اس کیو ال از یک تا آخرین عدد رو توش ریختم
بعد با NOT IN اطلاعات دو فیلد تازه ساخته شده رو سلکت کردم و داخل دیتا ریدر ریختم و در آخر اطلاعات دیتا ریدر رو تو لیست باکس ریختم

میزان کاری که انجام شده بصورت دقیق : 6000 رکورد به فیلد اول منتقل شد.7500 رکورد از 1 تا 7500 شماره گذاری شد.7500رکورد باهم مقایسه شد.14 تا به لیست باکس منتقل شد. در 3 ثانیه