`
netxdiy
  • 浏览: 714671 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

SQL Server 2012中快速插入批量数据的示例及疑惑

 
阅读更多

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)


创建示例数据库

IF OBJECT_ID('DemoPager2012') IS NOT NULL
DROP DataBase DemoPager2012
GO

CREATE Database DemoPager2012
GO

USE DemoPager2012
GO

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

/*
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), ' ', '0'),'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,效果立竿见影

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), ' ', '0'),'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

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), ' ', '0'),'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插入

TRUNCATE table Customers
GO

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

SET STATISTICS IO ON;
SET STATISTICS TIME ON;
GO

DECLARE @d Datetime
SET @d=getdate();

/*****运用CTE递归插入,速度较快,邀月注***********************/
WITH Seq (num,CustomerNumber, CustomerName, CustomerCity) AS
(SELECT 1,cast('0000'as CHAR(4)),cast('Customer 0' AS NVARCHAR(50)),cast('X-City' as NVARCHAR(20))
UNION ALL
SELECT num + 1,Cast(REPLACE(STR(num, 4), ' ', '0') AS CHAR(4)),
cast('Customer ' + STR(num,6) AS NVARCHAR(50)),
cast(CHAR(65 + (num % 26)) + '-City' AS NVARCHAR(20))
FROM Seq
WHERE num <= 10000
)
INSERT INTO Customers (CustomerNumber, CustomerName, CustomerCity)
SELECT CustomerNumber, CustomerName, CustomerCity
FROM Seq
OPTION (MAXRECURSION 0)

select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())

SET STATISTICS IO OFF ;
SET STATISTICS TIME OFF;
GO


邀月工作室

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

邀月补充:

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

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

邀月注:本文版权由邀月和CSDN共同所有,转载请注明出处。
助人等于自助! 3w@live.cn




分享到:
评论

相关推荐

    SpringBoot整合Mybatis连接SQL Server 跨库批量插入

    本篇将深入探讨如何在Spring Boot项目中整合Mybatis,实现对SQL Server数据库的跨库批量插入操作。 首先,我们需要在Spring Boot项目中引入相关的依赖。对于Mybatis的支持,我们需要添加Mybatis和其Spring Boot ...

    C#实现批量插入sqlserver数据

    在C#编程中,批量插入数据到SQL Server数据库是一个常见的需求,特别是在处理大量数据时,效率至关重要。本篇文章将详细探讨三种不同的批量插入方法:常规的`INSERT`语句、`SqlBulkCopy`类以及使用表值参数。我们将...

    Sqlserver大数据量插入速度慢或丢失数据的解决方法

    ### Sqlserver大数据量插入速度慢或丢失数据的解决方法 #### 概述 在处理大量数据插入SQL Server数据库的过程中,可能会遇到插入速度慢或者数据丢失的问题。这种情况通常出现在需要批量插入数千甚至上万条记录的...

    sql下三种批量插入数据的方法

    第二种方法使用的是SqlBulkCopy,使您可以用其他源的数据有效批量加载 SQL Server 表;第三种使用的方法是sql server中的表值参数方法,表值参数是 SQL Server 2008 中的新参数类型。表值参数是使用用户定义的表类型...

    SQL Server 2012驱动包

    -批量数据上传:批量插入、更新和删除记录。 5. **性能优化** - 预编译SQL语句:使用PreparedStatement,减少解析开销。 - 执行计划缓存:启用Statement对象的`prepareCall(String sql, int resultSetType, int ...

    sqlserver 批量创建表

    以上两种方式都是在SQL Server 2008中批量插入数据的有效手段。 在实际应用中,我们还需要考虑一些其他因素,比如事务处理以确保数据的完整性和一致性,错误处理以捕获并解决可能出现的问题,以及性能优化,如合理...

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

    在SQL Server中,批量插入数据是提高数据处理效率的关键技术,尤其当需要处理大量记录时。本文将介绍两种批量插入数据的方法:使用普通的INSERT语句和使用SqlBulkCopy类。 首先,我们创建一个用于测试的数据库`...

    用sql语句由excel表往sqlserver数据库表中导数据

    - `OPENROWSET`函数允许您直接从外部数据源(如Excel文件)读取数据并将其插入到SQL Server数据库中。 - 示例SQL语句如下: ```sql SELECT * INTO aaa FROM OPENROWSET( 'Microsoft.Jet.OLEDB.4.0', 'Excel ...

    SQL批量录入数据到数据库中

    在SQL(Structured Query Language)中,批量录入数据是常见的数据库操作任务,特别是在测试环境中,我们需要快速地填充大量的示例数据。本话题将详细介绍如何在MS SQL Server中进行批量数据录入,以及分享一种实用...

    ACCESS和SQL批量插入数据工具

    这款工具专为数据库管理员和开发人员设计,用于快速、高效地向ACCESS和SQL Server数据库中批量插入数据,尤其在进行负荷测试时,它能显著提高工作效率。 首先,我们来了解一下ACCESS。ACCESS是Microsoft Office套件...

    详解MyBatis直接执行SQL查询及数据批量插入

    在本文中,我们将深入探讨如何使用MyBatis直接执行SQL查询以及如何进行数据的批量插入。 **一、直接执行SQL查询** 在MyBatis中,你可以通过Mapper接口和XML配置文件来直接执行自定义的SQL查询。下面是一个简单的...

    SQLServer中防止并发插入重复数据的方法详解

    总之,防止SQL Server中的并发插入重复数据可以通过多种方式实现,包括数据库级别的约束、条件查询以及事务隔离级别和锁的巧妙使用。在设计数据库时,应根据具体业务需求和预期的并发负载来选择最合适的策略。

    易语言SQLServer插入数据源码

    在SQL Server插入数据时,我们通常会使用`INSERT INTO`语句。例如,如果我们有一个名为`Employees`的表,包含`ID`,`Name`和`Department`三个字段,我们可以编写如下的SQL语句: ```sql INSERT INTO Employees (ID,...

    C#.NET中如何批量插入大量数据到数据库中

    2. **批量插入(Bulk Insert)**:SQL Server 提供了一个`SqlBulkCopy`类,用于快速地将大量数据从一个数据源(如DataTable或DataReader)复制到SQL Server表中。这比逐行插入要快得多。 ```csharp using ...

    C# 对SqlServer中Image字段的读写(例子)

    在SQL Server数据库中,`Image`数据类型用于存储大量的二进制数据,如图片、文档等。在C#编程环境中,我们经常需要处理这类数据,包括从数据库读取`Image`字段并显示为图片,或者将图片数据写入数据库。本篇文章将...

    解决SQLServer最大流水号的方法

    SQL Server 中,最大流水号是指在插入数据时,自动增长的唯一标识符。然而,在实际应用中,我们可能会遇到最大流水号的问题,那么如何解决这个问题呢?本文将介绍两种解决 SQL Server 最大流水号的方法。 方法一:...

    SQLServer2000数据库与Excel数据表转换C#实现

    可以使用OpenXML SDK或者Microsoft.Office.Interop.Excel来读取Excel文件,然后创建SqlDataAdapter和DataSet,通过DataTable对象将数据加载到DataSet,最后使用SqlBulkCopy类批量插入到SQL Server数据库中。...

    SQLSERVER中对Image(大对象)对象操作

    在SQL Server数据库管理系统中,`Image`数据类型用于存储大对象(LOB,Large Object),如图片、文档或二进制数据。本篇文章将深入探讨如何在SQL Server中对`Image`对象进行操作,包括插入、查询、更新和删除等基本...

    sql server 大数据量插入 有源码

    在VS源码中,可能包含了实现批量插入的示例代码,这有助于快速高效地处理大量数据。 存储过程是另一种有效的策略,它允许预编译的SQL代码在服务器端执行,减少了网络往返次数。在`sourceCode\bigsqlrunner\src\...

    C#实现Excel导入数据到SQL Server数据库

    本教程将聚焦于使用C#编程语言实现从Excel文件批量导入数据到SQL Server数据库的过程,利用`SqlBulkCopy`类来高效地完成这一任务。 首先,`SqlBulkCopy`是.NET Framework中的一个强大工具,它提供了将大量数据一次...

Global site tag (gtag.js) - Google Analytics