تا %60 تخفیف خرید برای 6 نفر با صدور مدرک فقط تا
00 00 00

آموزش درج رکوردهای انبود در SQL سرور با سی شارپ یا Bulk Import

حسین احمدی
حسین احمدی
3 پسند
557 بازدید
4 نظر
10 ماه قبل

عملیات درج رکورد ها در SQL Server به تعداد بالا می تونه خیلی زمان بر باشه، البته اگر به صورت عادی این کار انجام بشه. اما بوسیله قابلیت Bulk Insert یا درج انبوه رکوردها مدت زمان این کار به طرز چشم گیری کاهش پیدا می کنه. برای مثال، ممکنه شما قصد داشته باشید 1 میلیون رکورد رو در بانکتون INSERT کنید، گر تمام این رکورد ها رو خط به خط اجرا کنید این عملیات ممکنه ساعت ها طول بکشه، در حالی که بوسیله Bulk Insert این زمان حتی تا کمتر از 1 دقیقه هم کاهش پیدا می کنه. در این مطلب قصد داریم با نحوه Bulk Insert در SQL Server با کمک کلاس های DataTable و SqlBulkCopy آشنا بشیم.در ابتدا یک بانک و جدول نمونه با اسکریپت زیر ایجاد می کنیم:

create database SampleForBulkInsert;
go

create table SampleTable
(
 [Id] int identity not null primary key,
 [From] nvarchar(200) not null,
 [To] nvarchar(200) not null,
 [Date] datetime,
 [Balance] decimal not null
);
go

قطعه کد زیر عملیات درج رو به صورت رکورد به رکورد و استفاده مستقیم دستور INSERT INTO انجام میده. یعنی عملیات Bulk Insert نداریم:

Stopwatch sw = new Stopwatch();
sw.Start();
using (var cnn = new SqlConnection("data source=.; initial catalog=SampleForBulkInsert; user id=sa; password=1"))
{
    cnn.Open();
    for (int i = 0; i < 100000; i++)
    {
        var command = cnn.CreateCommand();
        command.CommandText = "insert into SampleTable values ('Hossein Ahmadi','Mohammad Nasiri',@date,10000);";
        command.Parameters.Add(new SqlParameter("date", DateTime.UtcNow));
        command.ExecuteNonQuery();
    }
}
sw.Stop();

Console.WriteLine(sw.Elapsed);

ما اینجا از کلاس StopWatch برای بدست آوردن مدت زمان اجرای کد استفاده کردیم که مدت زمان اجرا برای 100000 رکورد حدود 25 ثانیه بود:

00:00:25.7867841
Press any key to continue . . .

حالا عملیات درج رو برای 100000 رکورد با کلاس SqlBulkCopy و DataTable انجام میدیم:

Stopwatch sw = new Stopwatch();
sw.Start();

DataTable table = new DataTable();
table.Columns.Add("From", typeof(string));
table.Columns.Add("To", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
table.Columns.Add("Balance", typeof(decimal));

for (int i = 0; i < 100000; i++)
{
    var dataRow = table.NewRow();
    dataRow["From"] = "Hosein Ahmadi";
    dataRow["To"] = "Mohammad Nasiri";
    dataRow["Date"] = DateTime.UtcNow;
    dataRow["Balance"] = 10000;
    table.Rows.Add(dataRow);
}

using (var cnn = new SqlConnection("data source=.; initial catalog=SampleForBulkInsert; user id=sa; password=1"))
{
    SqlBulkCopy bulkCopy = new SqlBulkCopy(cnn);
    bulkCopy.ColumnMappings.Add("From", "From");
    bulkCopy.ColumnMappings.Add("To", "To");
    bulkCopy.ColumnMappings.Add("Date", "Date");
    bulkCopy.ColumnMappings.Add("Balance", "Balance");
    bulkCopy.DestinationTableName = "SampleTable";
    cnn.Open();
    bulkCopy.WriteToServer(table);
}
sw.Stop();

Console.WriteLine(sw.Elapsed);

مدت زمان اجرای کوئری بالا خیلی سریعتر از حالت درج تک به تک رکورد ها هست، حدود نیم ثانیه که نسبت به 25 ثانیه تفاوت چشم گیری داره:

00:00:00.5161634
Press any key to continue . . .

و درج حدود 1 میلیون رکورد:

00:00:05.8161634
Press any key to continue . . .

اما در کد بالا به ترتیب چه کاری انجام دادیم، در ابتدا تعریف یک DataTable که شامل ستون هایی معادل جدول ما در بانک اطلاعاتی هست:

DataTable table = new DataTable();
table.Columns.Add("From", typeof(string));
table.Columns.Add("To", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
table.Columns.Add("Balance", typeof(decimal));

در مرحله بعد اضافه کردن رکورد ها به DataTable:

for (int i = 0; i < 1000000; i++)
{
    var dataRow = table.NewRow();
    dataRow["From"] = "Hosein Ahmadi";
    dataRow["To"] = "Mohammad Nasiri";
    dataRow["Date"] = DateTime.UtcNow;
    dataRow["Balance"] = 10000;
    table.Rows.Add(dataRow);
}

و در نهایت درج رکورد ها در بانک اطلاعاتی:

using (var cnn = new SqlConnection("data source=.; initial catalog=SampleForBulkInsert; user id=sa; password=1"))
{
    SqlBulkCopy bulkCopy = new SqlBulkCopy(cnn);
    bulkCopy.ColumnMappings.Add("From", "From");
    bulkCopy.ColumnMappings.Add("To", "To");
    bulkCopy.ColumnMappings.Add("Date", "Date");
    bulkCopy.ColumnMappings.Add("Balance", "Balance");
    bulkCopy.DestinationTableName = "SampleTable";
    cnn.Open();
    bulkCopy.WriteToServer(table);
}

دو نکته که باید در کد بالا بهش توجه کنیم:

  1. اضافه کردن ColumnMapping برای مشخص کردن ستون های معادل در بانک اطلاعاتی
  2. مشخص کردن نام جدول بوسیله DestinationTableName

نویسنده: حسین احمدی
منبع: جزیره برنامه نویسی وب سایت توسینسو
هر گونه نشر و کپی برداری با ذکر نام منبع و نویسنده بلامانع است 

نظر شما
برای ارسال نظر باید وارد شوید.
4 نظر