码迷,mamicode.com
首页 > 其他好文 > 详细

一次性事务和CTE插入数据的比较

时间:2015-09-04 07:09:10      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:

有时要构造一些数据来做测试数据,像下面这样:

IF OBJECT_ID(NT14) IS NOT NULL
BEGIN
    DROP TABLE T14
END
GO
CREATE TABLE T14 (t14_id INT)
GO

DECLARE @i INT = 1
WHILE @i <= 1000
BEGIN
    INSERT INTO T14 (t14_id)
    SELECT @i
    SET @i = @i + 1
END
GO

code-1

 

这里存在一个问题,每运行一次insert相当于commit了一次事务,数据量小的还不会出现问题,如果把要插入100万,200万,1000万甚至更多的数据呢?既然insert语句是隐式commit的,在这个循环外面加一个显式的事务,即可显著提高插入的性能。另一种方法就是使用CTE也可以一次把数据插入到表中,从而提高性能。现在就这两种方法插入数据的性能来做一个比较。没有结果之前,猜猜哪种速度更快?或者两者差不多?

 

首先是加事务,插入100万条记录:

IF OBJECT_ID(NT14) IS NOT NULL
BEGIN
    DROP TABLE T14
END
GO
CREATE TABLE T14 (t14_id INT)
GO

DBCC FREESESSIONCACHE
DBCC DROPCLEANBUFFERS
GO

SET NOCOUNT ON;
BEGIN TRAN
DECLARE @i INT = 1
WHILE @i <= 1000000
BEGIN
    INSERT INTO T14 (t14_id)
    SELECT @i
    SET @i = @i + 1
END
COMMIT TRAN;
SET NOCOUNT OFF;
GO

code-2

 

我的机器上测试多次,取平均值,大概使用了22秒即可完成100万条记录的插入,速度还是挺快的。(如果没有加显式事务,要多久才能完成呢?有兴趣的朋友可以试下技术分享

 

下面是使用CTE:

IF OBJECT_ID(NT15) IS NOT NULL
BEGIN
    DROP TABLE T15
END
GO
CREATE TABLE T15 (t15_id INT)
GO

DBCC FREESESSIONCACHE
DBCC DROPCLEANBUFFERS
GO

WITH CTE1 AS ( 
SELECT a.[object_id] FROM master.sys.all_objects AS a, master.sys.all_objects AS b
)
,CTE2 AS (
SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) as row_no FROM CTE1
)

INSERT INTO T15 (t15_id)
SELECT row_no  FROM CTE2 WHERE row_no <= 1000000
GO

code-3

 

也是测试多次取平均值,竟然是5秒左右就完成,大大出乎我的意料!现在改为插入1000万条记录,看结果如何。前者只需把code-3中的1000000修改为10000000,再运行即可。后者由于CTE1的记录数不够,需要UNION ALL两次,代码如下:

IF OBJECT_ID(NT15) IS NOT NULL
BEGIN
    DROP TABLE T15
END
GO
CREATE TABLE T15 (t15_id INT)
GO

DBCC FREESESSIONCACHE
DBCC DROPCLEANBUFFERS
GO

WITH CTE1 AS ( 
SELECT a.[object_id] FROM master.sys.all_objects AS a, master.sys.all_objects AS b
UNION ALL
SELECT a.[object_id] FROM master.sys.all_objects AS a, master.sys.all_objects AS b
UNION ALL
SELECT a.[object_id] FROM master.sys.all_objects AS a, master.sys.all_objects AS b
)
,CTE2 AS (
SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) as row_no FROM CTE1
)

INSERT INTO T15 (t15_id)
SELECT row_no  FROM CTE2 WHERE row_no <= 10000000
GO

code-4

 

测试结果:加事务的插入大概需要3分多钟,而CTE则不超过1分半钟的时间就完成了。看来还是CTE更高效啊!在测试过程中,发现内存的使用量不多,但CPU的使用有较明显的提高。此外,插入大数据到表中,有无索引和日志恢复模式也会影响插入的性能。

一次性事务和CTE插入数据的比较

标签:

原文地址:http://www.cnblogs.com/fishparadise/p/4781035.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!