使用Ado.NET插入750条记录的最快方法是什么?

时间:2010-03-18 10:10:40

标签: sql-server ado.net

我们已经尝试使用orm mapper工具,但它打开en关闭连接750次。然后我们尝试构建一个批量插入,但这甚至更慢......

编辑:

CREATE TABLE [dbo].[DataWarehouse](
[DataWarehouseId] [int] IDENTITY(1,1) NOT NULL,
[ColumnName] [nvarchar](max) NOT NULL,
[ColumnValue] [nvarchar](max) NOT NULL,
[RRN] [nvarchar](50) NOT NULL,
[PackageSessionId] [int] NOT NULL,
[AccessCode] [nvarchar](100) NOT NULL,
[Selectie] [nvarchar](150) NOT NULL,
[Date] [smalldatetime] NOT NULL,
[PackageId] [int] NOT NULL,
[Category] [nvarchar](500) NULL,
[OrderId] [int] NOT NULL,
[Category2] [nvarchar](500) NULL,
[TestCode] [nvarchar](200) NULL,
[Category3] [int] NULL,
[QuestionSpecificCategory] [nvarchar](max) NULL,
 CONSTRAINT [PK_DataWarehouse] PRIMARY KEY CLUSTERED 
(
    [DataWarehouseId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
 ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

3 个答案:

答案 0 :(得分:5)

使用简单的SqlCommand应该足够快750行,除非你有一些非常繁重的字段,或者数据库中有一些非常昂贵的索引/约束:

var insert = new SqlCommand("INSERT INTO ...", connection);
var fooParam = insert.Parameters.Add("Foo", SqlType.Int);

for (int i = 0; i < 750; i++)
{
    fooParam.Value = i;
    insert.ExecuteNonQuery();
}

答案 1 :(得分:2)

在我的(最接近现有技术)机器上需要200到400毫秒。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Diagnostics;

namespace InsertSpeedTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var sw = new Stopwatch();
            sw.Start();
            using (var conn = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=SpeedTests;Integrated Security=True;"))
            {
                conn.Open();
                using (var tran = conn.BeginTransaction())
                {
                    using (var cmd = conn.CreateCommand())
                    {
                        cmd.CommandText = "insert into [dbo].[DataWarehouse] ( [ColumnName] , [ColumnValue] , [RRN] , [PackageSessionId] , [AccessCode] , [Selectie] , [Date] , [PackageId] , [Category] , [OrderId] , [Category2] , [TestCode] , [Category3] , [QuestionSpecificCategory]) values  ( @ColumnName , @ColumnValue , @RRN , @PackageSessionId , @AccessCode , @Selectie , @Date , @PackageId , @Category , @OrderId , @Category2 , @TestCode , @Category3 , @QuestionSpecificCategory)";
                        cmd.CommandType = CommandType.Text;
                        cmd.Transaction = tran;
                        cmd.Parameters.Add("@ColumnName", SqlDbType.NVarChar,-1);
                        cmd.Parameters.Add("@ColumnValue", SqlDbType.NVarChar, -1);
                        cmd.Parameters.Add("@RRN", SqlDbType.NVarChar, 50);
                        cmd.Parameters.Add("@PackageSessionId", SqlDbType.Int);
                        cmd.Parameters.Add("@AccessCode", SqlDbType.NVarChar, 100);
                        cmd.Parameters.Add("@Selectie", SqlDbType.NVarChar, 150);
                        cmd.Parameters.Add("@Date", SqlDbType.SmallDateTime);
                        cmd.Parameters.Add("@PackageId", SqlDbType.Int);
                        cmd.Parameters.Add("@Category", SqlDbType.NVarChar, 500);
                        cmd.Parameters.Add("@OrderId", SqlDbType.Int);
                        cmd.Parameters.Add("@Category2", SqlDbType.NVarChar, 500);
                        cmd.Parameters.Add("@TestCode", SqlDbType.NVarChar, 200);
                        cmd.Parameters.Add("@Category3", SqlDbType.Int);
                        cmd.Parameters.Add("@QuestionSpecificCategory", SqlDbType.NVarChar, -1);
                        cmd.Prepare();
                        for (int i = 0; i < 750; i++)
                        {
                            cmd.Parameters["@ColumnName"].Value = "Column " + i;
                            cmd.Parameters["@ColumnValue"].Value = "value " + i;
                            cmd.Parameters["@RRN"].Value = "prn" + i;
                            cmd.Parameters["@PackageSessionId"].Value = i;
                            cmd.Parameters["@AccessCode"].Value = "access code" + i;
                            cmd.Parameters["@Selectie"].Value = "selectio " + i;
                            cmd.Parameters["@Date"].Value = DateTime.Now.AddMinutes(i);
                            cmd.Parameters["@PackageId"].Value = i;
                            cmd.Parameters["@Category"].Value = "category " + i;
                            cmd.Parameters["@OrderId"].Value = 100000 + i;
                            cmd.Parameters["@Category2"].Value = "category2 " + i;
                            cmd.Parameters["@TestCode"].Value = "test code " + i;
                            cmd.Parameters["@Category3"].Value = 200000 + i;
                            cmd.Parameters["@QuestionSpecificCategory"].Value = "whatever " + i;
                            cmd.ExecuteNonQuery();
                        }
                        tran.Commit();
                    }
                }
            }
            sw.Stop();
            Debug.WriteLine(sw.ElapsedMilliseconds);
        }
    }
}

答案 2 :(得分:1)

最快:

  • 安排类似32项的块的插入。使用Workitem。
  • 在每个处理程序中,打开连接,提交包含所有32个插入的O​​NE sql语句。

结果:

  • 往返次数减少。请求的同步性使得提交请求有点贵 - 一次提交32次比一次提交32次要快。
  • 如果正确配置了SQL Server,则使用并行插入(遗憾的是,并不多)。它还意味着多个请求命中服务器而不等待下一批。