开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 2130|回复: 2
打印 上一主题 下一主题
收起左侧

[MSSQL] SQL Server: 局部变量是如何影响查询性能的

[复制链接]

跳转到指定楼层
楼主
发表于 2013-2-7 13:12:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式   天津市天津市
数据库开发者在存储过程和脚本中使用局部变量是很常见的事情,但是,局部变量会影响查询的性能,接下来我们来证实这一点。




数据库开发者在存储过程和脚本中使用局部变量是很常见的事情,但是,局部变量会影响查询的性能,接下来我们来证实这一点。

首先让我们创建一个表并插入一些测试数据:

USE AdventureWorks  GO  CREATE TABLE TempTable        (tempID UNIQUEIDENTIFIER,tempMonth INT, tempDateTime DATETIME )  GO   INSERT INTO TempTable (tempID, tempMonth, tempDateTime)  SELECT NEWID(),(CAST(100000*RAND() AS INT) % 12) + 1 ,GETDATE()  GO 100000 -- (EXECUTE THIS BATCH 100000 TIME)   -- Create an index to support our query  CREATE NONCLUSTERED INDEX [IX_tempDateTime] ON [dbo].[TempTable]  ([tempDateTime] ASC)  INCLUDE ( [tempID]) WITH ( ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]  GO 然后我们做一个简单的查询:

SET STATISTICS IO ON GO  SELECT * FROM TempTable  WHERE tempDateTime > '2012-07-10 03:18:01.640' Table 'TempTable'. Scan count 1, logical reads 80, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

检查这个执行计划以及索引检索的属性,你会发现预估行数是实际行数的两倍,但并不会太影响执行计划,因为优化器选择了最合适的查询方法:







查询优化器根据基本统计直方图来预估数据行数,即:EQ_ROWS + AVG_RANGE_ROWS (77 + 88.64286) DBCC SHOW_STATISTICS ('dbo.TempTable', IX_tempDateTime)




现在我们修改 SELECT 语句以使用局部变量,你会发现查询优化器使用了一个不同的查询计划,这是一个更耗时的计划,为什么?

DECLARE @RequiredDate DATETIME  SET @RequiredDate = '2012-07-10 03:18:01.640'  SELECT * FROM TempTable  WHERE tempDateTime  > @RequiredDate ------------------------------------------------------------------------------------------


Table 'TempTable'. Scan count 1, logical reads 481, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.





预估值和实际值差别更大,相当于查询优化器无法选择最适合的查询计划,因为错误的预估值。因为查询优化在执行时并不清楚局部变量值,导致无法使用统计直方图。

不等式运算符的情况

在我们的查询中使用的不等式运算符,因此查询优化器使用了一个简单的 30% 的算式来预估。

Estimated Rows =(Total Rows * 30)/100 = (100000*30)/100 = 30000

等式运算符的情况

DECLARE @RequiredDate DATETIME  SET @RequiredDate = '2012-07-10 03:18:01.640'  SELECT * FROM TempTable  WHERE tempDateTime  = @RequiredDate 如果在局部变量中使用等式运算符,那么查询优化器又会选择不同的公式,即 精确度 * 表记录总数. 执行下面查询可获取精确的值

DBCC SHOW_STATISTICS('dbo.TempTable', IX_tempDateTime)

All Density = 0.0007358352 Total Number of Rows in Table = 100000

Estimated Rows = Density * Total Number =  0.0007358352 *  100000 = 73.5835

英文原文:http://www.connectsql.blogspot.tw/2012/07/sql-server-how-local-variables-can.html

结帖率:67% (2/3)
沙发
发表于 2013-2-7 13:17:13 | 只看该作者   江苏省南通市
虽然,看不懂还是顶了
回复 支持 反对

使用道具 举报

结帖率:37% (7/19)
板凳
发表于 2013-2-15 09:38:07 | 只看该作者   北京市北京市
板凳呵呵      
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:[email protected]
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表