• 问题起因:

最近做的项目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性能测试的更多相关文章

  1. 性能测试培训:sql server性能测试分析局部变量的性能影响

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loadrunner的培训中,为了提高学员性能优化的经验,加入了 ...

  2. c# sqlsugar,hisql,freesql orm框架全方位性能测试对比 sqlserver 性能测试

    在2022年1月份本人做过一次sqlsugar,hisql,freesql三个框架的性能测试,上次主要是测的sqlserver下的常规插入(非bulkcopy的方式数据插入),hisql与目前比较流行 ...

  3. Jmeter性能测试 如何利用SQLserver造出大批的数据

    作为一个测试人员,需要做性能测试时候,如果没有实际数据,或者实际数据不适合做压测,就要自己着手造数据了. 以下面的接口测试为例,简单介绍下需要的数据: 这是一个会员注册接口,入参比较多,你可以选用全部 ...

  4. SQLServer语句执行效率及性能测试

    写程序的人,往往需要分析所写的SQL语句是否已经优化过了,服务器的响应时间有多快,这个时候就需要用到SQL的STATISTICS状态值来查看了. 通过设置STATISTICS我们可以查看执行SQL时的 ...

  5. Mongodb学习笔记三(Mongodb索引操作及性能测试)

    第三章 索引操作及性能测试 索引在大数据下的重要性就不多说了 下面测试中用到了mongodb的一个客户端工具Robomongo,大家可以在网上选择下载.官网下载地址:http://www.robomo ...

  6. SQL语句性能测试

    /* --Sqlserver 清楚执行缓存, 用于SQL语句性能测试 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE */

  7. SQLSERVER 数据库性能的的基本

    SQLSERVER 数据库性能的基本 很久没有写文章了,在系统正式上线之前,DBA一般都要测试一下服务器的性能 比如你有很多的服务器,有些做web服务器,有些做缓存服务器,有些做文件服务器,有些做数据 ...

  8. SQLServer中在视图上使用索引(转载)

    在SQL Server中,视图是一个保存的T-SQL查询.视图定义由SQL Server保存,以便它能够用作一个虚拟表来简化查询,并给基表增加另一层安全.但是,它并不占用数据库的任何空间.实际上,在你 ...

  9. SQLite介绍、学习笔记、性能测试

    SQLite介绍.学习笔记.性能测试 哪些人,哪些公司或软件在用SQLite: Nokia's Symbian,Mozilla,Abobe,Google,阿里旺旺,飞信,Chrome,FireFox可 ...

随机推荐

  1. Solr高亮详解

    hl.fl: 用空格或逗号隔开的字段列表.要启用某个字段的highlight功能,就得保证该字段在schema中是stored.如果该参数未被给出,那么就会高亮默认字段 standard handle ...

  2. 来到这里,我放弃了多少- UI基础-疯狂猜图,我们都疯狂了-

    小问题也要问 学习最重要的是 自律 我昨天晚上3点睡的, 这两天一点也没睡 0.99*0.99  每天差一点 日积月累就很多了 关键字,在字典里查一下,在类里面查查 瑞详博客下载器 跑步后精神多了,白 ...

  3. miniproject black jack--Fail

    第一部分 下载这个小项目的程序模板并回顾card类的定义.这个类已经执行了所以你的任务是自己熟悉下代码.开始,通过粘贴card类定义到程序模板中并验证我们的代码如预期那样工作. 实现“__init__ ...

  4. SQL注入攻击和防御

    部分整理...   什么是SQL注入? 简单的例子, 对于一个购物网站,可以允许搜索,price小于某值的商品 这个值用户是可以输入的,比如,100 但是对于用户,如果输入,100' OR '1'=' ...

  5. iOS开发入门教程

    iOS开发入门教程 http://my.oschina.net/mailzwj/blog/133273 摘要 iOS开发入门教程,从创建项目到运行项目,包括OC基础,调试,模拟器设置等相关知识. iO ...

  6. Android Handler简单示例

    package com.firstapp.foo.firstapp; import android.os.Handler; import android.os.Message; import andr ...

  7. mysql基本sql语句大全(提升用语篇)

    1.说明:复制表(只复制结构,源表名:a 新表名:b) (Access可用) 法一:select * into b from a where 1<>1(仅用于SQlServer) 法二:s ...

  8. ArcGIS中添加进自定义的ttf字符标记符号

    原文:ArcGIS中添加进自定义的ttf字符标记符号 ArcGIS系统中的样式可能不能满足实际生产需要,为了实现快速制图,可自定义一些样式,以便重复利用. 1.   制作的符号库 使用 FontCre ...

  9. 解决libc.so.6: version `GLIBC_2.14' not found问题

    今天centos新机器上运行项目的时候出现题目所示的错误,搜索后发现是底层glibc 版本太低导致. strings /lib64/libc.so.6 |grep GLIBC_ 使用上面的命令发现 g ...

  10. jq 拖拽

    1.尼玛, move事件的时候忘了加ev,找了一个多小时 <!DOCTYPE html> <html> <head lang="en"> < ...