SQL Server 中VARCHAR(MAX)变量赋值引起的性能问题。

简介: 原文:SQL Server 中VARCHAR(MAX)变量赋值引起的性能问题。案例环境:           操作系统版本 : Windows Server 2008 R2 Standard  SP1           数据库版本   :  Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64) 案例介绍:   由于不能将生产环境的代码和数据贴上来,所以我构造了下面一个小案例,当然没法和生产环境的案例一致。
原文: SQL Server 中VARCHAR(MAX)变量赋值引起的性能问题。

案例环境:

          操作系统版本 : Windows Server 2008 R2 Standard  SP1

          数据库版本   :  Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64)

案例介绍:

 

由于不能将生产环境的代码和数据贴上来,所以我构造了下面一个小案例,当然没法和生产环境的案例一致。只能是接近而已。但是足以反映问题本质就足够了。

DROP TABLE ProductPrice; 
 
GO 
 
CREATE TABLE ProductPrice 
 
( 
 
ProductName VARCHAR(14), 
 
Sequence INT , 
 
ProductPrice FLOAT 
 
) 
 
GO 
 

 

构造8000条测试数据,然后将数据插入临时表#tmp(其实完全可以不用临时表,只因为生产环境也是临时表,故模拟接近案例环境)

DECLARE @index INT =1;
DECLARE @subindex INT;
 
 WHILE @index <= 800
 BEGIN
 SET @subindex = 1;
 WHILE @subindex <=10
  BEGIN 
   INSERT INTO ProductPrice
    SELECT 'product' + convert(varchar,@index), @subindex, rand()*1000;
 
   SET @subindex = @subindex +1;
  END;
 
  SET @index = @index +1;
END
 
 
 
SELECT * INTO #tmp FROM ProductPrice;
GO

 

本来开发人人员也许是要使用动态SQL语句获取下面这样一段SQL语句(随意构造小例子,形似神不似)

 

DECLARE @sqlText NVARCHAR(MAX) =''; 
  
SELECT @sqlText=@sqlText+ quotename(productname)+
    '=CAST(MAX(CASE WHEN [productname]='+QUOTENAME(productname,'''')
      +' THEN [productPrice] END) AS VARCHAR)' 
FROM #tmp 
GROUP BY ProductName 
 
  

SELECT datalength(@sqlText);

 

 

clipboard

 

但是由于疏忽或是对动态SQL不了解,写成了这样一个SQL语句,结果执行时间一下子飚增到7分多钟。

 

DECLARE @sqlText NVARCHAR(MAX) =''; 
  
SELECT @sqlText=@sqlText+ quotename(productname)+
    '=CAST(MAX(CASE WHEN [productname]='+QUOTENAME(productname,'''')
      +' THEN [productPrice] END) AS VARCHAR)' 
FROM #tmp ; 
SELECT datalength(@sqlText);

 

clipboard[1]

看来SQL对于处理非常长的字符串对象有一定的性能问题,于是为了验证我的想法,我又构造了下面一个例子。创建临时表#tmp,数据来源于 sys.all_columns

 

DROP TABLE #tmp;
GO
SELECT * INTO #tmp FROM sys.all_columns;
GO
 
 
7364 行受影响)

然后我们来看一下下面SQL语句

DECLARE @output NVARCHAR(MAX)
SELECT @output=ISNULL(@output,'') + QUOTENAME(name) + REPLICATE('it is only a test ', 200)
FROM #tmp

那么我们来看看这条SQL的执行计划,如下所示,很普通的执行计划,看不出有啥特别之处。但是执行性能那叫一个糟糕透顶!

SET SHOWPLAN_ALL ON;
 
GO
 
DECLARE @output NVARCHAR(MAX)
 
SELECT @output=ISNULL(@output,'') + QUOTENAME(name) + REPLICATE('it is only a test ', 200)
 
FROM #tmp 

StmtText的内容,如下所示:

DECLARE @output NVARCHAR(MAX)

SELECT @output=ISNULL(@output,'') + QUOTENAME(name) + REPLICATE('it is only a test ', 200)

FROM #tmp

  |--Compute Scalar(DEFINE:([Expr1004]=isnull([@output],CONVERT_IMPLICIT(nvarchar(max),'',0))+quotename([tempdb].[dbo].[#tmp].[name])+N'it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is only a test it is onl'))

       |--Table Scan(OBJECT:([tempdb].[dbo].[#tmp]))

 

虽然能理解处理大对象需要很多资源,会产生一定的性能问题,但是执行时间这么长,还是让我觉得有点不可思议,但是又不清楚具体原因!

目录
相关文章
|
11月前
|
SQL
【YashanDB知识库】like 变量的SQL语句应用程序执行效率低与yasql执行效率高
【YashanDB知识库】like 变量的SQL语句应用程序执行效率低与yasql执行效率高
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
SQL 存储 数据采集
sql中varchar转number时报错怎么解决
通过上述策略的综合运用,面对VARCHAR到NUMBER的转换挑战,不仅能够游刃有余地解决现有的问题,更能前瞻性地预防未来的隐患。在数字化转型的浪潮中,凭借其高性能、安全稳定的云产品与服务,为各类企业级应用保驾护航,助您轻松驾驭数据的海洋,实现业务的无缝扩展与全球布局。
592 0
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
607 13
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
439 9
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
294 6
|
存储 SQL C++
对比 SQL Server中的VARCHAR(max) 与VARCHAR(n) 数据类型
【7月更文挑战7天】SQL Server 中的 VARCHAR(max) vs VARCHAR(n): - VARCHAR(n) 存储最多 n 个字符(1-8000),适合短文本。 - VARCHAR(max) 可存储约 21 亿个字符,适合大量文本。 - VARCHAR(n) 在处理小数据时性能更好,空间固定。 - VARCHAR(max) 对于大文本更合适,但可能影响性能。 - 选择取决于数据长度预期和业务需求。
1298 1
|
SQL 安全 Java
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
1644 0
|
SQL 监控 数据库
SQL Server 查询超时问题排查
【7月更文挑战第8天】排查 SQL Server 查询超时涉及五个主要方面:检查复杂查询、评估服务器性能、审视配置参数、更新统计信息和分析执行计划。关注点包括查询的结构(如连接、子查询和索引),服务器资源(CPU、内存、网络延迟),连接和内存设置,以及统计信息的时效性。通过这些步骤可定位并解决性能瓶颈。
646 0
|
存储 SQL 程序员
【Sql Server】存储过程通过作业定时执行按天统计记录
通过前两篇文章的学习,我们已经对创建表、存储过程、作业等功能点有所了解 本次将结合前面所学习的知识点,创建统计表以及结合作业定时按天以及实时统计域名各个长度的记录值
【Sql Server】存储过程通过作业定时执行按天统计记录