SqlServer数据插入性能小记

  对于SQL性能,已经很久没关注了。由于近期项目既没有几千万的海量数据也没有过多的性能要求,所以在性能上也就没下太多功夫。然而,前不久和朋友闲谈间话题一转就说到程序上了,他说他用Delphi做了个数据导入的功能,插入数据的时候感觉很慢。以个人对SQL的了解,就建议他使用批量插入的方式,并很认真的告诉他这样应该会快很多。而在实际工作中,类似批量导入数据的功能是非常常见的,也许一个不小心我们就搞挂了服务器。那就究竟要怎么做才能给服务器留条活路,让用户不用点完上传看部电影再看上传结果呢?为此做了个小实验,并简单说下自己的看法。

  环境:

    CPU : i7;

    内存 : 6G;

    数据库:SqlServer2008;

    数据量:10W

  

  实验内容:

    创建LoopInsert 和BatchInsert两个函数,LoopInsert中使用拼接的方式生成insert into xxx values(...) insert into xxx values(...) ...形式的sql执行并返回sql的执行时间,BatchInsert中同样使用拼接sql的方式生成insert into xxx values(...),(...),(...)形似的sql并返回sql的执行时间。利用控制台程序多次执行两个函数,并输出执行结果。

  表结构:

CREATE TABLE TQRCode
    (
      ID INT PRIMARY KEY  IDENTITY(1, 1) ,
      Name NVARCHAR(300) ,
      Remark NVARCHAR(300)
    )

  

  C#实现代码:

 1     public class DataInertTest
 2     {
 3         /// <summary>
 4         /// 循环插入
 5         /// </summary>
 6         /// <returns>执行时间(秒)</returns>
 7         public double LoopInsert(int count)
 8         {
 9             StringBuilder sql = new StringBuilder();
10             for (int i = 0; i < count; i++)
11             {
12                 sql.Append(" Insert into TQRCode(Name,Remark) values(‘这是第").Append(i).Append("条数据‘,‘这是第").Append(i).Append("条数据_remark‘) ");
13             }
14             //时间统计
15             var stopwatch = new Stopwatch();
16             stopwatch.Start();
17             new Helper().Excute(sql.ToString());
18             return stopwatch.Elapsed.TotalMilliseconds;
19         }
20
21         /// <summary>
22         /// 批量插入
23         /// </summary>
24         /// <returns>执行时间(秒)</returns>
25         public double BatchInsert(int count)
26         {
27             StringBuilder sql = new StringBuilder();
28             sql.Append(" Insert into TQRCode(Name,Remark) values ");
29             for (int i = 0; i < count; i++)
30             {
31
32                 sql.Append(" (‘这是第").Append(i).Append("条数据‘,‘这是第").Append(i).Append("条数据_remark‘) ");
33                 if (i % 500 == 0)
34                 {
35                     sql.Append(" Insert into TQRCode(Name,Remark) values ");
36                 }
37                 else if (i < count - 1)
38                 {
39                     sql.Append(",");
40                 }
41             }
42
43             //时间统计
44             var stopwatch = new Stopwatch();
45             stopwatch.Start();
46             new Helper().Excute(sql.ToString());
47             return stopwatch.Elapsed.TotalMilliseconds;
48         }
49     }

C#实现代码

  注:sqlserver中单次批量插入数据最多1000条否则会提示我们:The number of row value expressions in the INSERT statement exceeds the maximum allowed number of 1000 row values.  

 测试代码:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             for (int i = 0; i < 3; i++)
 6             {
 7                 var obj = new DataInertTest();
 8                 var t1 = obj.LoopInsert(100000);
 9                 var t2 = obj.BatchInsert(100000);
10
11                 Console.WriteLine("LoopInsert  : {0}", t1);
12                 Console.WriteLine("BatchInsert : {0}", t2);
13                 Console.WriteLine("--------------------------------------------------");
14
15             }
16             Console.ReadLine();
17         }
18     }

测试代码

  

  测试结果:

  执行了3次结果很明显,效率差距在10倍以上。批量插入的方式之所以比循环插入快,主要因为sqlserver中每个insert into 都是一个独立的事务,循环插入500条数据就是500个事务,而一次插入500条数据,就只有一个事务。事务减少了消耗自然也就小了。且频繁的事务提交相当影响数据库的性能,也就起到了影响整个系统性能的作用(嘿嘿,一不小心也许服务器就挂了)。

  需要注意的是,测试中因为数据量不大所以两种方式都是采用的一次入库的方式,这样做可以减少数据库连接次数。但是这样做有个很大的弊端:内存消耗会很大。10w数据的sql拼接还好,如果是100w行那就未必了。所以,如果单条数据较大,建议每几百或几千行的时候提交一次,这个数字具体多大需要量体裁衣,平衡内存消耗。

  

时间: 2024-10-09 21:08:08

SqlServer数据插入性能小记的相关文章

.NET批量大数据插入性能分析及比较

原文:.NET批量大数据插入性能分析及比较 数据插入使用了以下几种方式 1. 逐条数据插入2. 拼接sql语句批量插入3. 拼接sql语句并使用Transaction4. 拼接sql语句并使用SqlTransaction5. 使用DataAdapter6. 使用TransactionScope及SqlBulkCopy7. 使用表值参数 数据库使用SQL Server,脚本如下 create table TestTable(Id int ,Name nvarchar(20)) 程序中生成测试Dat

&quot;Entity Framework数据插入性能追踪&quot;读后总结

园友莱布尼茨写了一篇<Entity Framework数据插入性能追踪>的文章,我感觉不错,至少他提出了问题,写了出来,引起了大家的讨论,这就是一个氛围.读完文章+评论,于是我自己也写了个简单的程序试了试. 先晒一下代码: 两个简单的类: 1: /// <summary> 2: /// 消费者 3: /// </summary> 4: public class Consumer 5: { 6: public int CId { get; set; } 7: public

python 读取SQLServer数据插入到MongoDB数据库中

# -*- coding: utf-8 -*-import pyodbcimport osimport csvimport pymongofrom pymongo import ASCENDING, DESCENDINGfrom pymongo import MongoClientimport binascii '''连接mongoDB数据库'''client = MongoClient('10.20.4.79', 27017)#client = MongoClient('10.20.66.10

SQL从入门到基础&ndash;03 SQLServer基础1(主键选择、数据插入、数据更新)

一.SQL语句入门 1. SQL语句是和DBMS"交谈"专用的语句,不同DBMS都认SQL语法. 2. SQL语句中字符串用单引号. 3. SQL语句中,对于SQL关键字大小写不敏感,对于字符串值大小写敏感. 4. 创建表.删除表不仅可以手工完成,还可以执行SQL语句完成,在自动化部署.数据导入中用的很多,Create Table T_Person(Id int not NULL,Name nvarchar(50),Age int NULL).Drop Table T_Person1

[转载]SQLServer 批量插入数据的两种方法。

在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍SQL Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters).运行下面的脚本,建立测试数据库和表值参数. 复制代码 代码如下: --Create DataBase create database BulkTestDB; go use BulkTestDB; go --Creat

数据库插入或者更新大批量数据的性能优化

对于一些数据量较大的系统,数据库面临的问题除了查询效率低下,还有就是数据入库时间长.特别像报表系统,每天花费在数据导入上的时间可能会长达几个小时或十几个小时之久.因此,优化数据库插入性能是很有意义的. 经过对MySQL InnoDB的一些性能测试,发现一些可以提高insert效率的方法,供大家参考参考. 1.一条SQL语句插入多条数据 常用的插入语句如: INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`) VALUE

mybatis批量插入oracle大量数据记录性能问题解决

环境: mybatis  + oracle11g r2 1.使用"直接路径插入"(以下sql语句中的"/*+append_values */"),而且使用keyword"union all": <insert id="addUidCodeBatch" parameterType="java.util.List"> insert into /*+append_values */ T_UID_COD

SQLserver将一张表a的数据插入另一张表b

一.将一张表a的数据插入另一张表b(b为新建表) select * into 表b  from 表a 二.将一张表a的数据插入另一张表b(b为已有表) insert into 表b select * from 表a

sqlserver数据库插入数据

//插入一行数据INSERT [INTO] 表名 [(列名)] VALUES (值列表)注意事项:(1)每次插入一行数据,不能只插入半行或者几列数据 插入的数据是否有效将按照整行的完整性的要求来检验 (2)每个数据值的数据类型.精度和小数位数必须与相应的列匹配(3)不能为标识列指定值 (4)如果在设计表的时候就指定了某列不允许为空,则必须插入数据 (5)插入的数据项,要求符合检查约束的要求 (6)具有缺省值的列,可以使用DEFAULT(缺省)关键字来代替插入的数值源代码:INSERT INTO