SQL Server中几种遍历方式比较
SQL遍历解析
在SQL的存储过程,函数中,经常需要使用遍历(遍历table),其中游标、临时表等遍历方法很常用。面对小数据量,这几种遍历方法均可行,但是面临大数据量时,就需要择优选择,不同的遍历方法,在效率上存在指数级别的差异
本文列举了常用的3中遍历方法:游标、临时表、索引表,重点分析其效率。
本文主要针对大量数据的遍历,当数据量小时;可以随意选择一种遍历方法。
实例数据如下:一共177471条数据

需求:更新LDBM,其中LDBM=LXBM+LDXLH;即update V_TL_T_LD_ALL set LDBM=LXBM+LDXLH:为了演示遍历,我们循环遍历,一条条数据更新,同时统计其效率,并初略分析其原因
1.游标遍历
游标的遍历
游标是一种最常用的方法,使用起来比较简单,主要步骤为:声明游标,打开游标,使用游标,关闭游标和释放游标。示例代码如下
-- 方法1:游标
-- 声明变量
DECLARE
@LDBM AS NVARCHAR(20),
@LDXLH AS NVARCHAR(20),
@LXBM AS NVARCHAR(20),
@CROWID AS NVARCHAR(80); -- 声明游标
DECLARE T_LD CURSOR FAST_FORWARD FOR
SELECT LDBM,LDXLH,LXBM,CROWID
FROM V_TL_LD_ALL1 OPEN T_LD; -- 取第一条记录
FETCH NEXT FROM T_LD INTO @LDBM,@LDXLH,@LXBM,@CROWID; WHILE @@FETCH_STATUS=0
BEGIN
-- 操作
UPDATE V_TL_LD_ALL1 SET LDBM= @LDBM+' '+@LDXLH WHERE CROWID=@CROWID; -- 取下一条记录
FETCH NEXT FROM T_LD INTO @LDBM,@LDXLH,@LXBM,@CROWID;
END -- 关闭游标
CLOSE T_LD; -- 释放游标
DEALLOCATE T_LD;
游标是最直接的从表里面一条条的数据取出,并进行update操作,没有涉及到索引,如果数据量大,其取数据和update都将消耗大量的时间,因此此种方式效率很低。
从对数据库的操作上,其一共操作数据库2n+1次,将数据取出并存入游标(申明游标):1次;update更新操作:n次;从游标取记录:n次;将数据存储到游标和消耗了大量的内存,且随着数据量的增大,消耗值将呈现指数增加
更新上述177474条数据一共消耗了2h48min37s
2.临时表
使用游标不仅仅存在性能的问题,也违背面向集合思想的问题,所以我们有必要用面向集合的思想去找到一种更好的解决方案,即使用面向对象的思想,构造一个临时表,然后直接操作临时表,代码如下。
-- 方法2:使用临时表
-- 创建临时表
SELECT LDBM,LDXLH,LXBM,CROWID
INTO #T_LD
FROM V_TL_LD_ALL1 -- 声明变量
DECLARE
@LDBM AS NVARCHAR(20),
@LDXLH AS NVARCHAR(20),
@LXBM AS NVARCHAR(20),
@CROWID AS NVARCHAR(80); WHILE EXISTS(SELECT CROWID FROM #T_LD)
BEGIN
-- 也可以使用top 1
SET ROWCOUNT 1
SELECT @LXBM= LXBM, @LDXLH= LDXLH,@CROWID=CROWID FROM #T_LD;
UPDATE V_TL_LD_ALL1 SET LDBM= @LXBM+' '+@LDXLH WHERE CROWID=@CROWID;
SET ROWCOUNT 0 DELETE FROM #T_LD WHERE CROWID=@CROWID;
END
使用临时表,和游标类似,同时将大量的数据存储到内存中,但是随着遍历的进行,临时表的数据量越来越小,可以相当程度的降低内存的消耗,但是需要不停的与table表做交互,一共操作3n+1次数据库;
此种方式,更新上述数据一共消耗:1H:45min:37S
3.索引表
索引表和临时表的操作类似;唯一区别在于在建立临时表是,添加一个索引,然后通过此索引从表中取数据;效率上有所提升,但是增加了变量的输出,代码如下
--方法3:使用索引表
--创建临时表
IF EXISTS(Select Name From Sysobjects Where Name='tmpTable')
DROP table tmpTable --存在则删除
create table tmpTable(
NID int primary key identity(1,1), --主键,自增
CrowId nvarchar(90),
LXBM nvarchar(20),
LDXLH nvarchar(6),
)
--插入数据
insert into tmpTable(CrowId,LXBM,LDXLH)
select CrowId,LXBM,LDXLH from V_TL_LD_ALL1 -- 声明变量
DECLARE
@index int,
@countNum int,
@LDBM AS NVARCHAR(20),
@LDXLH AS NVARCHAR(20),
@LXBM AS NVARCHAR(20),
@CROWID AS NVARCHAR(80); select @countNum=count(1) from tmpTable;
set @index=0;
--遍历
while @index<@countNum
begin
set @index=@index+1;
select @LXBM= LXBM, @LDXLH= LDXLH,@CROWID=CROWID from tmpTable where NID=@index
UPDATE V_TL_LD_ALL1 SET LDBM= @LXBM+' '+@LDXLH WHERE CROWID=@CROWID;
end --删除临时索引表
DROP table tmpTable
临时索引表和临时表类似,区别在于:在取数据的时候,通过索引的方式取数据;相比临时表,减少了频繁操作数据库的次数,相比游标,减少了与数据库交互的时间(索引检索速度更快)
更新上述数据,一共消耗:1H2,min
比较而言,建议尽可能少的使用游标,不仅消耗内存,代码量也稍微复杂一些;当数据量小的时候,建议使用临时表(代码比较轻量),而随着数据的增加,建议使用索引表
SQL Server中几种遍历方式比较的更多相关文章
- Sql Server中的表访问方式Table Scan, Index Scan, Index Seek
1.oracle中的表访问方式 在oracle中有表访问方式的说法,访问表中的数据主要通过三种方式进行访问: 全表扫描(full table scan),直接访问数据页,查找满足条件的数据 通过row ...
- 转:Sql Server中的表访问方式Table Scan, Index Scan, Index Seek
0.参考文献 Table Scan, Index Scan, Index Seek SQL SERVER – Index Seek vs. Index Scan – Diffefence and Us ...
- HashMap 中7种遍历方式的性能分析
随着 JDK 1.8 Streams API 的发布,使得 HashMap 拥有了更多的遍历的方式,但应该选择那种遍历方式?反而成了一个问题. 本文先从 HashMap 的遍历方法讲起,然后再从性能. ...
- Sql Server中三种字符串合并方法的性能比较
文章来自:博客园-DotNet菜园 最近正在处理一个合并字符吕的存储过程,在一个测试系统的开发中,要使用到字符串合并功能,直接在Sql中做.示例:有表內容﹕名称 內容1 abc1 ...
- SQL Server的三种分页方式
直接上代码 --top not in方式 select top 条数 * from tablename where Id not in (select top 条数*页数 Id from tablen ...
- SQL Server中使用md5的方式
在SQl2005下自带的函数hashbytes() ,此函数是微软在SQL SERVER 2005中提供的,可以用来计算一个字符串的 MD5 和 SHA1 值,使用方法如下: --获取123456的M ...
- OC中四种遍历方式
标准的C语言for循环.Objective-C 1.0出现的NSEnumerator.Objective-C 1.0出现的for in快速遍历.块遍历. 遍历的话,一般是NSArray.NSDicti ...
- SQL Server 中几种常见的约束关系
1.创建唯一约束 当表中已创建主键,但又要保证其他数据列的值唯一时,可以使用唯一约束,并且唯一约束允许NULL值(只有一个) (1)展开指定的数据库: (2)右击要创建唯一约束的表,在弹出的快捷菜单中 ...
- Sql Server 中使用日期遍历
一个存储过程小案例,内容如下: declare @dt datetime set @dt='2016-01-01' while (@dt<='2016-12-31') begin -- 转换字符 ...
随机推荐
- 【RL-TCPnet网络教程】第36章 RL-TCPnet之FTP服务器
第36章 RL-TCPnet之FTP服务器 本章节为大家讲解RL-TCPnet的FTP服务器应用,学习本章节前,务必要优先学习第35章的FTP基础知识.有了这些基础知识之后,再搞本章节会有事 ...
- emWin录音机,含uCOS-III和FreeRTOS两个版本
第12期:录音机配套例子:V6-921_STemWin提高篇实验_录音机(uCOS-III)V6-922_STemWin提高篇实验_录音机(FreeRTOS) 例程下载地址: http://forum ...
- 惊奇!用Java也能实现比特币系统
最近区块链技术突然爆火,身边做技术的朋友茶余饭后不谈点区块链什么的都被认为是跟不上时代了,为啥会这样了? 这其实跟比特币价格去年的突飞猛进是分不开的,比特币价格从去年初不到一千美金到今年初最高接近两万 ...
- FFmpeg 结构体学习(七): AVIOContext 分析
在上文FFmpeg 结构体学习(六): AVCodecContext 分析我们学习了AVCodec结构体的相关内容.本文,我们将讲述一下AVIOContext. AVIOContext是FFMPEG管 ...
- 快速理解Token,Cookie,Session
在Web应用中,HTTP请求是无状态的.即:用户第一次发起请求,与服务器建立连接并登录成功后,为了避免每次打开一个页面都需要登录一下,就出现了cookie,Session. Cookie Cookie ...
- django中的跨表查询梳理
1.前言 最近在写一个小项目,里面主要涉及的就是表与表之间复杂的关系.当真正开发起来的时候,才发现自己对复杂的表关系间的查询有点混乱,趁着这几天的时间,重新梳理了一下. 2.概念 在开始之前,先明确几 ...
- 优化之Joiner组件
Joiner组件在运行时需要额外的内存空间处理中间结果,因此会影响性能 可通过查看Joiner performance计数器来决定Joiner组件是否需要优化 通过如下方式优化Joiner组件 将Ma ...
- 关于CGI 和 PHP-FPM需要弄清的
https://blog.csdn.net/gao_yu_long/article/details/79390510 补充一点: 如果php-cgi -b 127.0.0.1:6999,则6999端口 ...
- java代码之美(6)---guava之multimap
guava之multimap 上一篇讲到Multiset它可以对存入相同元素做一个计数的功能,那multimap呢? 一.概述 1.基本介绍和案例说明 multimap和MultiSet的继承结果很相 ...
- CSS,JavaScript知识点
1.css重用 <style> 如果整个页面的宽度 > 900px时: { . ...