SQL Server 2008中SQL应用系列--目录索引

今天在做一个案例演示时,在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)

创建示例数据库

示例表,该表只有四个字段。

  1. /*
    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条数据到该表中,语句如下:

  1. 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

该插入语句在SQL Server 2008 r2版本和SQL Server 2012版本中,测试结果如下:

令我惊讶的是,SQL Server 2012居然耗时达到5分多钟,而SQL Server 2008R2版,只需要大约6秒钟。更令人费解的是:查询的I/O统计和elapsed time,在这两个版本中几乎一样。对此异象,我只能理解为每次Insert时的毫秒级精度可能不足以度量该次操作带来的细小差距,然而累积起来就非常可观了。

解决方案一:使用 Set NoCount On,效果立竿见影

  1. 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

Set NoCount On(http://msdn.microsoft.com/zh-cn/library/ms189837.aspx)的作用:使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。这在批量插入时将显著提高性能。至于 本例中,为什么SQL Server 2008 R2版中却不受该开关影响,希望知道的同学不吝赐教,非常感谢。

改进解决方案二:使用 Set NoCount On+Transaction

  1. 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

解决方案三:使用递归CTE插入

小结:SQL Server 2012中批量插入数据时,请记得Set NoCount ON,并尽可能加上Transaction,当然,推荐使用CTE,这可能会带来性能上的巨大提升。

邀月补充:

后来与微软亚太工程师多次沟通,得出初步结论:

在不打开“set nocount on”时,SSMS 2012与SSMS 2008r2版本的UI在执行效率上可能有极大差异,而与SQL Server引擎没有明显相关。

SQL Server 2012中快速插入批量数据的示例及疑惑的更多相关文章

  1. (数据科学学习手册28)SQL server 2012中的查询语句汇总

    一.简介 数据库管理系统(DBMS)最重要的功能就是提供数据查询,即用户根据实际需求对数据进行筛选,并以特定形式进行显示.在Microsoft SQL Serve 2012 中,可以使用通用的SELE ...

  2. SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪

    来源:http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html  本文主要介绍SQL Server中记录数据变更的四个方法:触发器 ...

  3. 微软BI 之SSAS 系列 - 在SQL Server 2012 中开发 Analysis Services Multidimensional Project

    SQL Server 2012 中提供了开发 SSAS 项目的两种模型,一种是新增加的 Tabular Model 表格模型,另一种就是原始的 Multidimensional Model 多维模型. ...

  4. SQL Server备份时间段内插入的数据依旧进入了备份文件?(转载)

    问 MSSql我在本机测试了下.为了延长备份时间,找个大的数据库.开始完整备份bak然后再此库新建表,并增添数据.备份结束.==================还原备份后,在还原的数据库内发现新增的表 ...

  5. SQL Server 2012中Task是如何调度的?

    SQL Server 2012中Task是如何调度的?[原文来自:How It Works: SQL Server 2012 Database Engine Task Scheduling]     ...

  6. SQL Server存储过程中使用表值作为输入参数示例

    这篇文章主要介绍了SQL Server存储过程中使用表值作为输入参数示例,使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据,这样 ...

  7. 在SQL Server 2012中实现CDC for Oracle

    在上篇在SSIS 2012中使用CDC(数据变更捕获)中,介绍了如何在SSIS 2012中使用CDC,本文在此基础上介绍,如何通过Attunity提供的Change Data Capture Desi ...

  8. 在SQL Server 2012中如何使用分组集

    作者:Itzik Ben-Gan  翻译:张洪举 此文摘自作者的<Microsoft SQL Server 2012 T-SQL基础>. 分组集就是你据以分组的一个属性集.传统上,SQL中 ...

  9. SQL Server ->> DISABLE索引后插入更新数据再REBUILD索引 和 保留索引直接插入更新数据的性能差异

    之前对于“DISABLE索引后插入更新数据再REBUILD索引 和 保留索引直接插入更新数据的性能差异”这两种方法一直认为其实应该差不多,因为无论如何索引最后都需要被维护,只不过是个时间顺序先后的问题 ...

随机推荐

  1. Java 并发 线程的生命周期

    Java 并发 线程的生命周期 @author ixenos 线程的生命周期 线程状态: a)     New 新建 b)     Runnable 可运行 c)     Running 运行 (调用 ...

  2. SQL Server2012中的SequenceNumber

    http://www.cnblogs.com/CareySon/archive/2012/03/12/2391581.html https://q.cnblogs.com/q/53552/ https ...

  3. json 多重嵌套反序列化和序列化

    namespace ConsoleApplication1 {     class Program     {         static void Main(string[] args)      ...

  4. 仿简书分享:UIActivityViewController系统原生分享

    接下来介绍UIActivityViewController: 1. 创建要分享的数据内容,加在一个数组 ActivityItems里. NSString *textToShare = @"我 ...

  5. 1.1 office安装

    2013版安装链接: https://pan.baidu.com/s/1qYMuidA 密码: uj9e

  6. 图片验证码自动识别,使用tess4j进行验证码自动识别(java实现)

    1.下载tess4j依赖的jar包,maven中央库地址:<dependency>            <groupId>net.sourceforge.tess4j< ...

  7. 用 Python 脚本实现对 Linux 服务器的网卡流量监控

    *这篇文章网上已经有相关代码,为了加深印象,我做了相关批注,希望对朋友们有帮助 工作原理:基于/proc文件系统 Linux 系统为管理员提供了非常好的方法,使其可以在系统运行时更改内核,而不需要重新 ...

  8. SQL语句的优化

    1.创建索引 表中数据经常需要用的哪些字段数据进行过滤,则添加该字段的索引,索引相当如一本书的目录,能加快查询数据的速度:同时在新建索引的时候,将需要查询的列,在包含性 列中新增上去,能减少查询语句的 ...

  9. openstack私有云布署实践【16.2 Ubuntu1404 只有根分区镜像制作】

    之所以要只有根分区镜像,是因为在创建VM或者调整云主机的硬盘大小时,它能自动扩容.无需人工介入   在原来的物理机10.40.41.1的CentOS 6.7上制作镜像. 宿主机坱要安装KVM相关软件: ...

  10. 两年后的随笔+this的思考

    恍惚看到自己在博客园的文章,唯一的一篇已经是接近两年前,再看看自己的名字...已然中枪了 从两年前的.net初学者,到现在工作之后阴差阳错转为前端... 两年过去了,现在回想起来,感觉成长的太少... ...