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

但是由于疏忽或是对动态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);

看来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]))
虽然能理解处理大对象需要很多资源,会产生一定的性能问题,但是执行时间这么长,还是让我觉得有点不可思议,但是又不清楚具体原因!
SQL Server 中VARCHAR(MAX)变量赋值引起的性能问题。的更多相关文章
- SQL Server中VARCHAR(MAX)和NVARCHAR(MAX)使用时要注意的问题(转载)
在Microsoft SQLServer2005及以上的版本中,对于varchar(n).nvarchar(n)和varbinary(n)有了max的扩展.可以使用如:varchar(max).nva ...
- SQL SERVER中LIKE使用变量类型输出结果不同
前言:Sql Server中LIKE里面使用不同的变量类型导致查询结果不一致的问题,其实看似有点让人不解的现象背后实质跟数据类型的实现有关. 一.我们先来创建示例演示具体操作 CREATE TABLE ...
- SQL Server中 SET 和 SELECT 赋值有什么区别?
SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT.对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们并没有注意,其实这两种 ...
- SQL SERVER中SELECT和SET赋值相同点与不同点
SELECT和SET在SQL SERVER中都可以用来对变量进行赋值,但其用法和效果在一些细节上有些不同. 1. 在对变量赋值方面,SET是ANSI标准的赋值方式,SELECT则不是.这也是SET方式 ...
- SQL Server中提前找到隐式转换提升性能的办法
http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前 ...
- SQL SERVER中LIKE使用变量类型不同输出结果不一致解惑
一同事在写脚本时,遇到一个关于LIKE里面使用不同的变量类型导致查询结果不一致的问题,因为这个问题被不同的人问过好几次,索性总结一下,免得每次都要解释一遍,直接丢一篇博客岂不是更方便!其实看似有点让人 ...
- SQL Server中,varchar和nvarchar如何选择
正常情况下,我们使用varchar也可以存储中文字符,但是如果遇到操作系统是英文操作系统并且对中文字体的支持不全面时, 在SQL Server存储中文字符为varchar就会出现乱码(显示为??). ...
- Sql Server中三种字符串合并方法的性能比较
文章来自:博客园-DotNet菜园 最近正在处理一个合并字符吕的存储过程,在一个测试系统的开发中,要使用到字符串合并功能,直接在Sql中做.示例:有表內容﹕名称 內容1 abc1 ...
- SQL Server中varchar和nvarchar的区别
varchar(n) 长度为 n 个字节的可变长度且非 Unicode 的字符数据.n 必须是一个介于 1 和 8,000 之间的数值.存储大小为输入数据的字节的实际长度,而不是 n 个字节.nvar ...
随机推荐
- Spring 4 + Reactor Integration Example--转
原文地址:http://www.concretepage.com/spring-4/spring-4-reactor-integration-example Reactor is a framewor ...
- struts2学习笔记--拦截器(Interceptor)和登录权限验证Demo
理解 Interceptor拦截器类似于我们学过的过滤器,是可以在action执行前后执行的代码.是我们做web开发是经常使用的技术,比如权限控制,日志.我们也可以把多个interceptor连在一起 ...
- WebGIS中解决使用Lucene进行兴趣点搜索排序的两种思路
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 目前跟信息采集相关的一个项目提出了这样的一个需求:中国银行等 ...
- AppCan学习笔记----关闭页面listview动态加载数据
AppCan页面关闭 AppCan 的页面是由两个HTML组成,如果要完全关闭的话需要在主HTML eg.index.html中关闭,关闭方法:appcan.window.close(-1); 管道 ...
- 请求facebook授权时,返回错误
在请求facebook授权时,返回如下错误:所提供的网址不被应用程序配置所接纳.:应用程序的设置不允许一个或多个所提供的链接.它必须与网站的URL或Canvas的URL相符,或该域必须是应用程序的一个 ...
- 在ASP.NET Core中怎么使用HttpContext.Current
一.前言 我们都知道,ASP.NET Core作为最新的框架,在MVC5和ASP.NET WebForm的基础上做了大量的重构.如果我们想使用以前版本中的HttpContext.Current的话,目 ...
- react入门(1)
这篇文章也不能算教程咯,就算是自己学习整理的笔记把. 关于react一些相关的简介.优势之类的,随便百度一下一大堆,我就不多说了,可以去官网(http://reactjs.cn/)看一下. 这片主要讲 ...
- 在IIS7.5中ASP.NET调用cmd程序拒绝访问决绝方法小记
前言 昨天利用Github的Webhook实现自动部署站点,其中要调用命令行(cmd.exe)程序执行shell脚本. 在本地测试没有任何问题,部署到服务器之后,发现错误信息:访问拒绝. 问题 没有权 ...
- jQuery 判断是否包含某个属性
1.Get the attribute, check the value var attr = $(this).attr('name'); // For some browsers, `attr` i ...
- SQL Server 存储过程遇到“表 '#TT' 没有标识属性。无法执行 SET 操作”错误
创建临时表,往临时表插入数据的时候报的错误. 一开始提示没有打开主键,后来打开主键就提示上述错误异常. 从网上查找资料没有找到,然后又到群里问各位大牛,一位大牛告诉我是没有设置主键. 我又仔细看看提示 ...

