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);

    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
  • 测试结果:

@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

时间: 2024-10-13 02:45:38

SqlServer StringToTable性能测试的相关文章

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

poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loadrunner的培训中,为了提高学员性能优化的经验,加入了很多服务器方面的优化知识,为性能调优的能力打下基础.今天sqlserver的性能测试方面的知识.(大家对课程感兴趣,请加qq:564202718) 性能测试的分析都有一定的方法和思路,这次我们来看看sqlserver方面的性能的知识. 数据库开发者在存储过程和脚本中使用局部变量,但是,局部变量会影响

Sqlserver 查询语句性能测试

写程序的人,往往需要分析所写的SQL语句是否已经优化过了,服务器的响应时间有多快,这个时候就需要用到SQL的STATISTICS状态值来查看了. 通过设置STATISTICS我们可以查看执行SQL时的系统情况.选项有PROFILE,IO ,TIME.介绍如下: SET STATISTICS PROFILE ON:显示分析.编译和执行查询所需的时间(以毫秒为单位). SET STATISTICS IO ON:报告与语句内引用的每个表的扫描数.逻辑读取数(在高速缓存中访问的页数)和物理读取数(访问磁

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

写程序的人,往往需要分析所写的SQL语句是否已经优化过了,服务器的响应时间有多快,这个时候就需要用到SQL的STATISTICS状态值来查看了. 通过设置STATISTICS我们可以查看执行SQL时的系统情况.选项有PROFILE,IO ,TIME. 介绍如下: SET STATISTICS PROFILE ON:显示分析.编译和执行查询所需的时间(以毫秒为单位). SET STATISTICS IO ON:报告与语句内引用的每个表的扫描数.逻辑读取数(在高速缓存中访问的页数)和物理读取数(访问

[转]性能测试(并发负载压力)测试分析-简要篇

在论坛混了多日,发现越来越多的性能测试工程师基本上都能够掌握利用测试工具来作负载压力测试,但多数人对怎样去分析工具收集到的测试结果感到无从下手,下面我就把个人工作中的体会和收集到的有关资料整理出来,希望能对大家分析测试结果有所帮助. 分析原则:    • 具体问题具体分析(这是由于不同的应用系统,不同的测试目的,不同的性能关注点)    • 查找瓶颈时按以下顺序,由易到难.    服务器硬件瓶颈-〉网络瓶颈(对局域网,可以不考虑)-〉服务器操作系统瓶颈(参数配置)-〉中间件瓶颈(参数配置,数据库

软件性能测试指标及其注意地方

并发性能测试的种类与指标 并发性能测试的种类取决于并发性能测试工具监控的对象,以QALoad自动化负载测试工具为例.软 件针对各种测试目标提供了DB2.DCOM.ODBC.ORACLE.NETLoad.Corba.QARun.SAP.SQLServer. Sybase.Telnet.TUXEDO.UNIFACE.WinSock.WWW.Java scrīpt等不同的监控对象,支持Windows和UNIX测试环境. 最关键的仍然是测试过程中对监控对象的灵活应用,例如目前三层结构的运行模式广泛使用,

性能测试结果分析

转自网络 性能测试工程师基本上都能够掌握利用测试工具来作负载.压力测试,但多数人对怎样去分析工具收集到的测试结果感到无从下手,下面我就把个人工作中的体会和收集到的有关资料整理出来,希望能对大家分析测试结果有所帮助. 分析原则: 1. 具体问题具体分析(这是由于不同的应用系统,不同的测试目的,不同的性能关注点) 2. 查找瓶颈时按以下顺序,由易到难. 服务器硬件瓶颈-〉网络瓶颈(对局域网,可以不考虑)-〉服务器操作系统瓶颈(参数配置)-〉中间件瓶颈(参数配置,数据库,web服务器等)-〉应用瓶颈(

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

在SQL Server中,视图是一个保存的T-SQL查询.视图定义由SQL Server保存,以便它能够用作一个虚拟表来简化查询,并给基表增加另一层安全.但是,它并不占用数据库的任何空间.实际上,在你查询它之前,视图并不做任何事情. 索引视图 在SQL Server 2000和2005中,你能够给视图增加索引.但是,如果视图只是一个保存在数据库中的查询定义,在运行前没有自己的数据,你如何给那个定义建立一个索引呢?嗯,这比较麻烦. 索引视图是一个已被物化或保存在数据库中的视图.当基本表更新时,给视

[转]检测SQLSERVER数据库CPU瓶颈及内存瓶颈

在任务管理器中看到sql server 2000进程的内存占用,而在sql server 2005中,不能在任务管理器中查看sql server 2005进程的内存占用,要用 以下语句查看sql server 的实际内存占用: select * from sysperfinfo where counter_name like '%Memory%' 其中, Total Server Memory 表示内存占用. select locked_page_allocations_kb  from sys

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

SQLite介绍.学习笔记.性能测试 哪些人,哪些公司或软件在用SQLite: Nokia's Symbian,Mozilla,Abobe,Google,阿里旺旺,飞信,Chrome,FireFox可见SQLite的稳定性及性能是不会有什么问题的,详细列表请参见:http://www.sqlite.org/famous.html. 网上关于SQLite的介绍一抓一大把,总结起来,他有如下特点: SQLite优点及适应场合: 轻量级绿色组件单一文件跨平台查询效率极高使用事务插入速度极快支持limi