案例环境:

操作系统版本 : 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)变量赋值引起的性能问题。的更多相关文章

  1. SQL Server中VARCHAR(MAX)和NVARCHAR(MAX)使用时要注意的问题(转载)

    在Microsoft SQLServer2005及以上的版本中,对于varchar(n).nvarchar(n)和varbinary(n)有了max的扩展.可以使用如:varchar(max).nva ...

  2. SQL SERVER中LIKE使用变量类型输出结果不同

    前言:Sql Server中LIKE里面使用不同的变量类型导致查询结果不一致的问题,其实看似有点让人不解的现象背后实质跟数据类型的实现有关. 一.我们先来创建示例演示具体操作 CREATE TABLE ...

  3. SQL Server中 SET 和 SELECT 赋值有什么区别?

    SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT.对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们并没有注意,其实这两种 ...

  4. SQL SERVER中SELECT和SET赋值相同点与不同点

    SELECT和SET在SQL SERVER中都可以用来对变量进行赋值,但其用法和效果在一些细节上有些不同. 1. 在对变量赋值方面,SET是ANSI标准的赋值方式,SELECT则不是.这也是SET方式 ...

  5. SQL Server中提前找到隐式转换提升性能的办法

        http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前 ...

  6. SQL SERVER中LIKE使用变量类型不同输出结果不一致解惑

    一同事在写脚本时,遇到一个关于LIKE里面使用不同的变量类型导致查询结果不一致的问题,因为这个问题被不同的人问过好几次,索性总结一下,免得每次都要解释一遍,直接丢一篇博客岂不是更方便!其实看似有点让人 ...

  7. SQL Server中,varchar和nvarchar如何选择

    正常情况下,我们使用varchar也可以存储中文字符,但是如果遇到操作系统是英文操作系统并且对中文字体的支持不全面时, 在SQL Server存储中文字符为varchar就会出现乱码(显示为??). ...

  8. Sql Server中三种字符串合并方法的性能比较

    文章来自:博客园-DotNet菜园 最近正在处理一个合并字符吕的存储过程,在一个测试系统的开发中,要使用到字符串合并功能,直接在Sql中做.示例:有表內容﹕名称  內容1     abc1      ...

  9. SQL Server中varchar和nvarchar的区别

    varchar(n) 长度为 n 个字节的可变长度且非 Unicode 的字符数据.n 必须是一个介于 1 和 8,000 之间的数值.存储大小为输入数据的字节的实际长度,而不是 n 个字节.nvar ...

随机推荐

  1. 在博客中使用LaTeX插入数学公式

    在博客中使用LaTeX插入数学公式 在学习机器学习中会接触到大量的数学公式,所以在写博客是会非常的麻烦.用公式编辑器一个一个写会非常的麻烦,这时候我们可以使用LaTeX来插入公式. 写这篇博文的目的在 ...

  2. 附录E 安装Kafka

    E.1   安装Kafka E.1.1    下载Kafka Kafka是由LinkedIn设计的一个高吞吐量.分布式.基于发布订阅模式的消息系统,使用Scala编写,它以可水平扩展.可靠性.异步通信 ...

  3. ZOJ Problem Set - 1006 Do the Untwist

    今天在ZOJ上做了道很简单的题目是关于加密解密问题的,此题的关键点就在于求余的逆运算: 比如假设都是正整数 A=(B-C)%D 则 B - C = D*n + A 其中 A < D 移项 B = ...

  4. hibernate笔记--组件映射方法

    假设我们需要保存学生student的信息,student中有一个address属性,我们知道像这种信息其值可能会有多个,就像一个人会有两个以上的手机号,这种情况在hibernate中应该这样配置: 新 ...

  5. Spring Boot启动流程详解(一)

    环境 本文基于Spring Boot版本1.3.3, 使用了spring-boot-starter-web. 配置完成后,编写了代码如下: @SpringBootApplication public ...

  6. supervisor 安装、配置、常用命令

    前言 在 web 应用部署到线上后,需要保证应用一直处于运行状态,在遇到程序异常.报错等情况,导致 web 应用终止时,需要保证程序可以立刻重启,继续提供服务. 所以,就需要一个工具,时刻监控 web ...

  7. C# 操作数据库表和数据库

    <1>c#创建数据库表: private void CreatTable(string name)      //创建数据库源数据表,name为表名 { con.ConnectionStr ...

  8. js动态的把左边列表添加到右边,可上下移动。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. laravel5 数据库配置(MySQL)

    laravel5 数据库配置(MySQL) 首先有一个安装完成可以运行的laravel框架. 配置database.php 进入laravel根目录. 在config目录下找到database.php ...

  10. 安卓模拟器genymotion连接eclipse成功但是不显示其中项目

    安卓模拟器困了我两三天了,原装模拟器比较慢,忍受不了,查到安卓模拟器的神器——genymotion 按照网上的步骤一步步都安装完毕,最后打开后发现,genymotion界面里面没有找到新建的工程, 这 ...