7.数据库存储(LEVELI&II)的难点:高速数据插入

请关注个人小站http://sqlhis.com/

笔者在这个项目中使用的是SQL SERVER数据库。

网络上搜索“SQL SERVER高速数据插入”,可以获得很多结果。大致上是:
.使用C#的SqlBulkCopy类,这个插入功能确实速度不错,但是我对底层的实现很疑惑,怀疑可能是一个特殊的接口,当然这个以后可以探索一下。
.使用Bulk Insert,这需要生成特定格式的文件,然后通过文件导入,一次性导入还好,想做到程序里面就相当困难了
.直接使用insert语句,把insert串起来,多个insert做成一个事务。这个方法不会太快。

笔者想介绍一下使用用户定义表类型(User-Defined Table Types)配合存储过程来进行插入,这是我目前测试的最高速的插入。

第一步:建立一个用户自定义表类型,代码如下:

CREATE TYPE dbo.udtt_TickData AS TABLE
(
SecId int NOT NULL,
BizDate int NOT NULL,
TradeTime int NOT NULL,
Price int NULL
PRIMARY KEY(SecId,BizDate,TradeTime)
)

测试一下这个用户定义表类型

--声明一个变量@t,类型为AType
declare @t udtt_TickData--往变量@t中插入2条数据
insert into @t (SecId,BizDate,TradeTime,Price)
select 1,20200101,9030000,1
union all
select 1,20200101,9030001,1
--显示变量@t中数据
select * from @t


第二步,建立一个表TickData容纳数据

 CREATE TABLE TickData
(
SecId int NOT NULL,
BizDate int NOT NULL,
TradeTime int NOT NULL,
Price int NULL
PRIMARY KEY(SecId,BizDate,TradeTime)
)

第三步,建立存储过程接收从用户自定义表类型传入的数据

 CREATE PROCEDURE [dbo].updTickData
@p_ImportData udtt_TickData READONLY --输入表值参数
AS
BEGIN
INSERT TickData
SELECT * FROM @p_ImportData
END

第四步,通过存储过程插入数据

--声明一个变量@t,类型为AType
declare @t udtt_TickData--往变量@t中插入2条数据
insert into @t (SecId,BizDate,TradeTime,Price)
select 1,20200101,9030000,1
union all
select 1,20200101,9030001,1
--清除掉TickData的数据
TRUNCATE TABLE TickData

--显示变量@t中数据
exec updTickData @t

select * from TickData

完成了以上4步,一个简单的通过用户定义表类型插入的范例就完成了。我们还没有使用程序写入,我们继续构建一个C#程序,C#程序构造一个DataTable,作为存储过程的参数插入即可。

使用C#构建一个控制台应用程序

static void Main(string[] args)
 {
   using (SqlConnection connTarget = new SqlConnection("Data Source=192.168.3.22;Initial                             Catalog=TESTDB;User       ID=sa;Password=XXXXX"))
    {
       connTarget.Open();
       SqlCommand commond = connTarget.CreateCommand();//构建DataTable
       DataTable dt = new DataTable();
       dt.Columns.Add("SecId", Type.GetType("System.Int32"));
       dt.Columns.Add("BizDate", Type.GetType("System.Int32"));
       dt.Columns.Add("TradeTime", Type.GetType("System.Int32"));
       dt.Columns.Add("Price", Type.GetType("System.Int32"));
       DataRow row = dt.NewRow();
       row[0] = 1;
       row[1] = 20200101;
       row[2] = 9030000;
       row[3] = 1;
       dt.Rows.Add(row);
       DataRow row2 = dt.NewRow();
       row2[0] = 1;
       row2[1] = 20200101;
       row2[2] = 9030001;
       row2[3] = 1;
       dt.Rows.Add(row2);

       //DataTable作为参数传入
       commond.CommandType = CommandType.StoredProcedure;
       commond.CommandText = "updTickData";
       commond.Parameters.AddWithValue("@p_ImportData", dt);
       commond.ExecuteNonQuery();
       connTarget.Close();
    }
 }

全部完成,在实际应用中,注意每个构造的DataTable的行数需要多一点,几千到几万行提交一次会比较好,具体如何选择可以在实际程序中进行测试,选定最佳行数。

注意:使用此方法还有一个优点,当DataTable传入存储过程中后,后续的处理自由度大,可以是单独的INSERT,也可以使用MERGE,甚至更多更复杂的语句。

posted @ 2020-05-20 10:28  artmouse  阅读(255)  评论(0编辑  收藏  举报