SqlServer StringToTable性能测试
- 问题起因:
最近做的项目DB数据量比较大(基本上一个月的数据就是10亿),而工程中Proc参数中包含有id拼接字符串,id拼接字符串格式:1,2,4,5,100,301。当数据量很小的情况下,这样做没有问题,但一旦数据量到达亿级,运行会很耗时,比如:当这样的参数id拼接字符串中包含有10万个id的时候(我们实际应用中确实有这么多个id需要传到数据库,而且这样的id是从库中取出后,又经过程序的筛选后剩余的id),像这样的语句:
Declare @IDS nvarchar(max);
Set @IDS='10w个id用逗号分割组成的字符串';
Select T10.TEXT,T10.Name FROM DX.M as T10 inner join dbo.StringToTable(@IDS,',') as T11 on T10.ID=T11.ID;
执行了18个小时还未查询出数据。
备注:
虚拟机配置:内存:64G;CPU核数:40。
- DBA建议:
我测试了下,性能还算可以。在解析5000个逗号之内性能还行,太多了,性能就急速下降了。
最初的那个版本其实还是很常用的,性能要比改写之后的要好一些(在字符串特别长的情况下)。但是同样存在,如果字符串太长,性能急速下降的问题。
如果真的有5W以上逗号的字符串。这个SqlServer在执行计划上会消耗很多性能。
(自己也可以测试一下解析5000个逗号串和解析5W个字符串的差距,并不是5000字符串消耗时间*10的线性关系)
所以应当写一个循环,一次处理一部分。
比如以下两种方法:
1. 每次截取前1W个字符串,解析出来之后插入到临时表,然后在解析后面的,在插入到临时表,循环处理。最后临时表和实际表进行关联。
insert into #t1
select id
from dbo.stringtotable(@字符串1)
insert into #t1
select id
from dbo.stringtotable(@字符串2)
2。用in的方式,每次where条件 in 一部分。然后将结果union all起来。
类似如下
select id
from table a
where id in (@字符串1)
union all
select id
from table a
where id in (@字符串2)
两种方法都可行。在字符串较短的情况下,第二种方法应该好一些。字符串较长,第一种应该好一些。
- 测试代码:
Declare @MRE_MROOIDS Nvarchar(Max); Set @MRE_MROOIDS='2,4,5,396009,';
--Set @MRE_MROOIDS='2,4,5,6,7,8,9,10,11,14,15,16,17,18,20,21,23,24,25,26,29,30'; Declare @SplitChar nvarchar(2);
Declare @EndIndex int;
Declare @Step int;
Declare @LastChars nvarchar(MAX);
Declare @CurrentTempChars nvarchar(max); Set @LastChars=@MRE_MROOIDS;
Set @Step=5000;
Set @EndIndex=0;
Set @SplitChar=','; IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects where id=OBJECT_ID(N'tempdb..#StringToTableEntry_Temp10'))
Begin
Drop Table #StringToTableEntry_Temp10;
End Create Table #StringToTableEntry_Temp10(ID INT); While(LEN(@LastChars)>@Step)
Begin
Set @EndIndex= charindex(@SplitChar,@LastChars,@Step);
If @EndIndex=0 Begin
Return;
End
Set @CurrentTempChars=SubString(@LastChars,0,@EndIndex);
-- insert into temp table
Insert Into #StringToTableEntry_Temp10
Select Id from dbo.StringToTable2(@CurrentTempChars,','); Set @LastChars=SubString(@LastChars,@EndIndex+1,LEN(@LastChars)-@EndIndex+1)
--Select @LastChars as LastChars;
Set @EndIndex=@EndIndex+@Step;
End If LEN(@LastChars)>0 Begin
Insert Into #StringToTableEntry_Temp10
Select Id from dbo.StringToTable2(@LastChars,',');
End Select COUNT(0) From #StringToTableEntry_Temp10
StringToTable2函数:
ALTER FUNCTION [dbo].[StringToTable]
(
@ids [nvarchar](max),
@separator [char](1)
)
RETURNS @IdsTable TABLE
(
[Id] INT NOT NULL
)
AS
BEGIN
IF(RIGHT(@ids,1)=@separator)
BEGIN
SET @ids=SUBSTRING(@ids,0,LEN(@ids));
END --下面的方式性能更好
IF(LEN(@ids) > 0)
BEGIN
DECLARE @i int;
SET @i = CHARINDEX(@separator, @ids); WHILE @i > 0
BEGIN
INSERT @IdsTable VALUES(LEFT(@ids, @i - 1));
SET @ids = SUBSTRING(@ids, @i + 1, LEN(@ids) - @i);
SET @i = CHARINDEX(@separator, @ids);
END IF(LEN(@ids) > 0)
BEGIN
INSERT @IdsTable VALUES(@ids);
END
END
RETURN;
END
- 测试结果:(以下测试结果均是Set Statitistics Time,IO on测试,如果不开始IO,Timer Statistics会比这个结果块很多)
@MRE_MROOIDS包含id记录 |
@Step长度 |
执行时间 |
100,000 |
100000 |
00:09:15 |
100,000 |
20000 |
00:03:48 |
100,000 |
10000 |
00:01:57 |
100,000 |
5000 |
00:01:01(不开启IO,Timer Statistics,耗时12s) |
SqlServer StringToTable性能测试的更多相关文章
- 性能测试培训:sql server性能测试分析局部变量的性能影响
poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loadrunner的培训中,为了提高学员性能优化的经验,加入了 ...
- c# sqlsugar,hisql,freesql orm框架全方位性能测试对比 sqlserver 性能测试
在2022年1月份本人做过一次sqlsugar,hisql,freesql三个框架的性能测试,上次主要是测的sqlserver下的常规插入(非bulkcopy的方式数据插入),hisql与目前比较流行 ...
- Jmeter性能测试 如何利用SQLserver造出大批的数据
作为一个测试人员,需要做性能测试时候,如果没有实际数据,或者实际数据不适合做压测,就要自己着手造数据了. 以下面的接口测试为例,简单介绍下需要的数据: 这是一个会员注册接口,入参比较多,你可以选用全部 ...
- SQLServer语句执行效率及性能测试
写程序的人,往往需要分析所写的SQL语句是否已经优化过了,服务器的响应时间有多快,这个时候就需要用到SQL的STATISTICS状态值来查看了. 通过设置STATISTICS我们可以查看执行SQL时的 ...
- Mongodb学习笔记三(Mongodb索引操作及性能测试)
第三章 索引操作及性能测试 索引在大数据下的重要性就不多说了 下面测试中用到了mongodb的一个客户端工具Robomongo,大家可以在网上选择下载.官网下载地址:http://www.robomo ...
- SQL语句性能测试
/* --Sqlserver 清楚执行缓存, 用于SQL语句性能测试 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE */
- SQLSERVER 数据库性能的的基本
SQLSERVER 数据库性能的基本 很久没有写文章了,在系统正式上线之前,DBA一般都要测试一下服务器的性能 比如你有很多的服务器,有些做web服务器,有些做缓存服务器,有些做文件服务器,有些做数据 ...
- SQLServer中在视图上使用索引(转载)
在SQL Server中,视图是一个保存的T-SQL查询.视图定义由SQL Server保存,以便它能够用作一个虚拟表来简化查询,并给基表增加另一层安全.但是,它并不占用数据库的任何空间.实际上,在你 ...
- SQLite介绍、学习笔记、性能测试
SQLite介绍.学习笔记.性能测试 哪些人,哪些公司或软件在用SQLite: Nokia's Symbian,Mozilla,Abobe,Google,阿里旺旺,飞信,Chrome,FireFox可 ...
随机推荐
- MySQL并发调优和IO调优
一.myisam的IO调优1.myisam通常在每次写入后把索引的改变刷写到磁盘上.所以批处理通常会更快点.做到这点,可以通过LOCK TABLES,他可以把写入控制到对表解锁.还可以用delay_k ...
- 例题.点击按钮显示内容+弹窗效果+ajax
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- selenium webdriver
http://www.blogjava.net/qileilove/archive/2014/02/18/409975.html Selenium VS Webdriver Selen ...
- 通过nginx配置文件抵御攻击
通过nginx配置文件抵御攻击 囧思九千 · 2013/11/12 12:22 0x00 前言 大家好,我们是OpenCDN团队的Twwy.这次我们来讲讲如何通过简单的配置文件来实现nginx防御攻击 ...
- 轮询、select、 epoll
网卡设备对应一个中断号, 当网卡收到网络端的消息的时候会向CPU发起中断请求, 然后CPU处理该请求. 通过驱动程序 进而操作系统得到通知, 系统然后通知epoll, epoll通知用户代码. 一. ...
- android 5.0 (lollipop)源码编译环境搭建(Mac OS X)
硬件环境:MacBook Pro Retina, 13-inch, Late 2013 处理器 2.4 GHz Intel Core i5 内存 8 GB 1600 MHz DDR3 硬盘60G以 ...
- 从while(cin>>a)开始探讨cin
1. 首先cin>>a返回的是左操作数,也就是返回cin. cin的条件状态中: cin.eof() 判断流是否到达文件的结束符 cin.fail() 判断IO操作是否失败 在 ...
- Anacodna之conda与 virtualenv对比使用教程,创建虚拟环境
conda创建虚拟环境 1.查看包 conda list查看安装了哪些包 conda env list查看有哪些虚拟环境 conda -V查看conda的版本 2.创建虚拟环境,命名为myflaska ...
- JavaScript学习之对象
JavaScript对象 一.对象简介 JavaScript 是面向对象的编程语言 (OOP).OOP 语言使我们有能力定义自己的对象和变量类型.注意:对象只是一种特殊的数据.对象拥有属性和方法. 1 ...
- MFC之目录结构及消息流转(一)
跟上时代,用vs2010, 新建一个MFC应用程序Helloworld. 目录结构: 所有文件分为6个部分:解决方案相关文件.工程相关文件.应用程序头文件和源文件.资源文件.预编译头文件和编译链接生成 ...