SQL Server 2012中快速插入批量数据的示例及疑惑
今天在做一个案例演示时,在SQL Server 2012中使用Insert语句插入1万条数据,结果遇到了一个奇怪的现象,现将过程分享出来,以供有兴趣的同学参考。
附:我的测试环境为:
SQL Server 2012,命名实例
Microsoft SQL Server 2012 - 11.0.2100.60 (Intel X86)
Feb 10 2012 19:13:17
Copyright (c) Microsoft Corporation
Enterprise Edition on Windows NT 6.0 <X86> (Build 6002: Service Pack 2)
创建示例数据库
示例表,该表只有四个字段。
- /*
- Setup script to create the sample table and fill it with
- sample data.
- */
- IF OBJECT_ID('Customers','U') IS NOT NULL
- DROP TABLE Customers
- CREATE TABLE Customers ( CustomerID INT primary key identity(1,1),
- CustomerNumber CHAR(4),
- CustomerName VARCHAR(50),
- CustomerCity VARCHAR(20) )
- GO
- /*
现在展示批量插入10000条数据到该表中,语句如下:
- TRUNCATE table Customers
- GO
- ----清除干扰查询
- DBCC DROPCLEANBUFFERS
- DBCC FREEPROCCACHE
- SET STATISTICS IO ON;
- SET STATISTICS TIME ON;
- GO
- DECLARE @d Datetime
- SET @d=getdate();
- declare @i int=1
- while @i<=10000
- begin
- INSERT INTO Customers (CustomerNumber, CustomerName,
- CustomerCity)
- SELECT REPLACE(STR(@i, 4), ' ', ''),'Customer ' + STR(@i,6),
- CHAR(65 + (@i % 26)) + '-City'
- set @i=@i+1
- end
- select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())
- SET STATISTICS IO OFF ;
- SET STATISTICS TIME OFF;
- GO
- TRUNCATE table Customers
该插入语句在SQL Server 2008 r2版本和SQL Server 2012版本中,测试结果如下:
令我惊讶的是,SQL Server 2012居然耗时达到5分多钟,而SQL Server 2008R2版,只需要大约6秒钟。更令人费解的是:查询的I/O统计和elapsed time,在这两个版本中几乎一样。对此异象,我只能理解为每次Insert时的毫秒级精度可能不足以度量该次操作带来的细小差距,然而累积起来就非常可观了。
解决方案一:使用 Set NoCount On,效果立竿见影
- TRUNCATE table Customers
- GO
- ----清除干扰查询
- DBCC DROPCLEANBUFFERS
- DBCC FREEPROCCACHE
- SET STATISTICS IO ON;
- SET STATISTICS TIME ON;
- GO
- DECLARE @d Datetime
- SET @d=getdate();
- set nocount on
- declare @i int=1
- while @i<=10000
- begin
- INSERT INTO Customers (CustomerNumber, CustomerName,
- CustomerCity)
- SELECT REPLACE(STR(@i, 4), ' ', ''),'Customer ' + STR(@i,6),
- CHAR(65 + (@i % 26)) + '-City'
- set @i=@i+1
- end
- select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())
- SET STATISTICS IO OFF ;
- SET STATISTICS TIME OFF;
- GO
- TRUNCATE table Customers
Set NoCount On(http://msdn.microsoft.com/zh-cn/library/ms189837.aspx)的作用:使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。这在批量插入时将显著提高性能。至于 本例中,为什么SQL Server 2008 R2版中却不受该开关影响,希望知道的同学不吝赐教,非常感谢。
改进解决方案二:使用 Set NoCount On+Transaction
- TRUNCATE table Customers
- GO
- ----清除干扰查询
- DBCC DROPCLEANBUFFERS
- DBCC FREEPROCCACHE
- SET STATISTICS IO ON;
- SET STATISTICS TIME ON;
- GO
- DECLARE @d Datetime
- SET @d=getdate();
- set nocount on
- declare @i int=1
- BEGIN TRANSACTION
- while @i<=10000
- begin
- INSERT INTO Customers (CustomerNumber, CustomerName,
- CustomerCity)
- SELECT REPLACE(STR(@i, 4), ' ', ''),'Customer ' + STR(@i,6),
- CHAR(65 + (@i % 26)) + '-City'
- set @i=@i+1
- end
- COMMIT
- select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())
- SET STATISTICS IO OFF ;
- SET STATISTICS TIME OFF;
- GO
- TRUNCATE table Customers
解决方案三:使用递归CTE插入
小结:SQL Server 2012中批量插入数据时,请记得Set NoCount ON,并尽可能加上Transaction,当然,推荐使用CTE,这可能会带来性能上的巨大提升。
邀月补充:
后来与微软亚太工程师多次沟通,得出初步结论:
在不打开“set nocount on”时,SSMS 2012与SSMS 2008r2版本的UI在执行效率上可能有极大差异,而与SQL Server引擎没有明显相关。
SQL Server 2012中快速插入批量数据的示例及疑惑的更多相关文章
- (数据科学学习手册28)SQL server 2012中的查询语句汇总
一.简介 数据库管理系统(DBMS)最重要的功能就是提供数据查询,即用户根据实际需求对数据进行筛选,并以特定形式进行显示.在Microsoft SQL Serve 2012 中,可以使用通用的SELE ...
- SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪
来源:http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html 本文主要介绍SQL Server中记录数据变更的四个方法:触发器 ...
- 微软BI 之SSAS 系列 - 在SQL Server 2012 中开发 Analysis Services Multidimensional Project
SQL Server 2012 中提供了开发 SSAS 项目的两种模型,一种是新增加的 Tabular Model 表格模型,另一种就是原始的 Multidimensional Model 多维模型. ...
- SQL Server备份时间段内插入的数据依旧进入了备份文件?(转载)
问 MSSql我在本机测试了下.为了延长备份时间,找个大的数据库.开始完整备份bak然后再此库新建表,并增添数据.备份结束.==================还原备份后,在还原的数据库内发现新增的表 ...
- SQL Server 2012中Task是如何调度的?
SQL Server 2012中Task是如何调度的?[原文来自:How It Works: SQL Server 2012 Database Engine Task Scheduling] ...
- SQL Server存储过程中使用表值作为输入参数示例
这篇文章主要介绍了SQL Server存储过程中使用表值作为输入参数示例,使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据,这样 ...
- 在SQL Server 2012中实现CDC for Oracle
在上篇在SSIS 2012中使用CDC(数据变更捕获)中,介绍了如何在SSIS 2012中使用CDC,本文在此基础上介绍,如何通过Attunity提供的Change Data Capture Desi ...
- 在SQL Server 2012中如何使用分组集
作者:Itzik Ben-Gan 翻译:张洪举 此文摘自作者的<Microsoft SQL Server 2012 T-SQL基础>. 分组集就是你据以分组的一个属性集.传统上,SQL中 ...
- SQL Server ->> DISABLE索引后插入更新数据再REBUILD索引 和 保留索引直接插入更新数据的性能差异
之前对于“DISABLE索引后插入更新数据再REBUILD索引 和 保留索引直接插入更新数据的性能差异”这两种方法一直认为其实应该差不多,因为无论如何索引最后都需要被维护,只不过是个时间顺序先后的问题 ...
随机推荐
- Django之模型管理器filter处理问题
今天上班第一天,恭祝所有朋友新年快乐!! 最近在github上发现一个还不错的基于Django的开源博客项目,不过也许是版本原因,其中代码存在着些许问题,今天主要记录下其中的模型处理方法的部分. 这段 ...
- 窗口、easyui-window、easyui-panel、easyui-linkbutton
//窗口 <script type="text/javascript" src="js/jquery.min.js"></script> ...
- js的兼容技巧
javascript原生代码中经常会遇到各式各样浏览器不兼容的问题,浏览器真是倔强,解决浏览器的兼容是前端猿们的一大难题 为了避免在工作中遇到这些简单的问题.节约开发时间,在这里总结一些常用的浏览器兼 ...
- 多线程随笔一(AutoResetEvent和ManulResetEvent)
AutoResetEvent和ManulResetEvent是.net中用来做线程的同步的两个类.从类名上不难看出,这两个类的区别在于一个是自动的,一个是手动的(这不是废话嘛).两个类的实现原理大致相 ...
- PhotoSwipe简介
官方网站http://www.photoswipe.com/源码示例http://github.com/downloads/codecomputerlove/PhotoSwipe/code.photo ...
- MySQL的保留关键字,使用时尽量避免
今天用phpmyadmin时,注意到一个提示: 列名 'update' 是一个MySQL 保留关键字. 突然意识到还是应该尽量避免这些保留关键字,也百度了一下.找到了这些关键字,列出来下 使用mysq ...
- 通过mvn archetype:generate创建Maven项目模板慢的问题
通过mvn archetype:generate这种交互方式来创建Maven项目模板的时候,经常会长时间卡在Generating project in Interactive mode这一行提示(图1 ...
- Char device registration
The kernel uses structures of type struct cdev to represent char devices internally. Include <lin ...
- Javaweb 第12天 JSP、EL技术
第12天 JSP.EL技术 今日任务: JSP技术入门和常用指令 JSP的内置对象&标签介绍 EL表达式&EL的内置对象 课堂笔记 1.JSP技术入门和常用指令 1.1.JSP的由来. ...
- Directed Roads
Directed Roads 题目链接:http://codeforces.com/contest/711/problem/D dfs 刚开始的时候想歪了,以为同一个连通区域会有多个环,实际上每个点的 ...