对于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行那就未必了。所以,如果单条数据较大,建议每几百或几千行的时候提交一次,这个数字具体多大需要量体裁衣,平衡内存消耗。

  

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

  1. 大数据应用之HBase数据插入性能优化实测教程

    引言: 大家在使用HBase的过程中,总是面临性能优化的问题,本文从HBase客户端参数设置的角度,研究HBase客户端数据批量插入性能优化的问题.事实胜于雄辩,数据比理论更有说服力,基于此,作者设计 ...

  2. "Entity Framework数据插入性能追踪"读后总结

    园友莱布尼茨写了一篇<Entity Framework数据插入性能追踪>的文章,我感觉不错,至少他提出了问题,写了出来,引起了大家的讨论,这就是一个氛围.读完文章+评论,于是我自己也写了个 ...

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

    # -*- coding: utf-8 -*-import pyodbcimport osimport csvimport pymongofrom pymongo import ASCENDING, ...

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

    数据插入使用了以下几种方式 1. 逐条数据插入2. 拼接sql语句批量插入3. 拼接sql语句并使用Transaction4. 拼接sql语句并使用SqlTransaction5. 使用DataAda ...

  5. 大数据应用之HBase数据插入性能优化之多线程并行插入测试案例

    一.引言: 上篇文章提起关于HBase插入性能优化设计到的五个参数,从参数配置的角度给大家提供了一个性能测试环境的实验代码.根据网友的反馈,基于单线程的模式实现的数据插入毕竟有限.通过个人实测,在我的 ...

  6. .NET 百万级 大数据插入、更新 ,支持多种数据库

    功能介绍  (需要版本5.0.44) 大数据操作ORM性能瓶颈在实体转换上面,并且不能使用常规的Sql去实现 当列越多转换越慢,SqlSugar将转换性能做到极致,并且采用数据库最佳API 操作数据库 ...

  7. c# 国内外ORM 框架 dapper efcore sqlsugar freesql hisql sqlserver数据常规插入测试性能对比

    c# 国内外ORM 框架 dapper efcore sqlsugar freesql hisql sqlserver数据常规插入测试性能对比对比 在6.22 号发布了 c# sqlsugar,his ...

  8. SQLServer 批量插入数据的两种方法

    SQLServer 批量插入数据的两种方法-发布:dxy 字体:[增加 减小] 类型:转载 在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Ins ...

  9. 一次EF批量插入多表数据的性能优化经历

    距离上次的博客已经有15个多月了,感慨有些事情还是需要坚持,一旦停下来很有可能就会停很久或者从此再也不会坚持.但我个人一直还坚持认为属于技术狂热份子,且喜欢精益求精的那种.最近遇到两个和数据迁移相关的 ...

  10. SQL从入门到基础–03 SQLServer基础1(主键选择、数据插入、数据更新)

    一.SQL语句入门 1. SQL语句是和DBMS“交谈”专用的语句,不同DBMS都认SQL语法. 2. SQL语句中字符串用单引号. 3. SQL语句中,对于SQL关键字大小写不敏感,对于字符串值大小 ...

随机推荐

  1. 3.21 Linux PATH环境变量及作用(初学者必读)

    在讲解 PATH 环境变量之前,首先介绍一下 which 命令,它用于查找某个命令所在的绝对路径.例如: [root@localhost ~]# which rm /bin/rm [root@loca ...

  2. GPU 环境搭建指南:使用 GPU Operator 加速 Kubernetes GPU 环境搭建

    本文主要分享如何使用 GPU Operator 快速搭建 Kubernetes GPU 环境. 1. 概述 上一篇文章 GPU 使用指南:如何在裸机.Docker.K8s 等环境中使用 GPU 分享了 ...

  3. Emoji表情字符大全增强你的表达能力-记事本也可以有情感,总有一个您用得上,复制粘贴即可,赶紧收藏关注!!!

    这是手绘的吗?不,它是Emoji表情字符,就是普通的文本,你不相信? ️️️️️️ 上面的内容,你看得见吗?尝试选中复制一下,再粘贴到其它地方? 我在PC上和Android手机上操作都是正常的 这是记 ...

  4. 【昌哥IT课堂】MySQL8.0新特性之不可见主键

    一.概述作为 MySQL DBA ,相信大家都经历过在复制模式下,如果没有主键,遇到 load data ,大事务,ddl 等有大量表数据行扫描的行为时,会带来严重的主从延迟,给数据库稳定性和数据一致 ...

  5. Rider离线使用Nuget包的方法

    有时候,我们的开发环境可能没有网络,vs也不太好安装. 这时候我们就可以使用Rider.但是没有Nuget的话,很多东西用起来很复杂. 所以这里介绍一下Rider离线配置Nuget的方法. 从Nuge ...

  6. 【实战问题】-- 布隆过滤器的三种实践:手写,Redission以及Guava(2)

    前面我们已经讲过布隆过滤器的原理[实战问题]-- 缓存穿透之布隆过滤器(1),都理解是这么运行的,那么一般我们使用布隆过滤器,是怎么去使用呢?如果自己去实现,又是怎么实现呢? 目录 布隆过滤器 手写布 ...

  7. 开源 - Ideal库 - Excel帮助类,ExcelHelper实现(四)

    书接上回,前面章节已经实现Excel帮助类的第一步TableHeper的对象集合与DataTable相互转换功能,今天实现进入其第二步的核心功能ExcelHelper实现. 01.接口设计 下面我们根 ...

  8. 『玩转Streamlit』--表单Form

    在Streamlit中,Form组件是一种特殊的UI元素,允许用户输入数据而不立即触发应用的重新运行. 这对于创建需要用户输入多个参数后再进行处理的交互式表单非常有用. 1. 概要 Form组件的主要 ...

  9. Vue.js 文本交替滚动

    1.前言 当一段文本需要单行显示,但是又限于容器宽度无法完全展示时,我们需要对其滚动展示,所以就有了这个插件,如图: 2.封装思路 使用js模拟循环滚动的动画,容器宽度固定且超出隐藏,文本元素禁止换行 ...

  10. 构建你的.NET Aspire解决方案

    .NET Aspire 是一组功能强大的工具.模板和包,用于构建可观察的生产就绪应用程序..NET Aspire 通过处理特定云原生问题的 NuGet 包集合提供.云原生应用程序通常由小型互连部分或微 ...