以下的文章主要向大家讲述的是正确优化SQL Server内存占用的执行缓存的实际操作方案,使用参数化查询来对执行缓存占用进行减少。我们主要是通过如下例子来说明一下正确使用参数化查询对缓存占用的影响。
为方便试验,我们使用了一台没有其它负载的SQL Server进行如下实验。
下面的脚本循环执行一个简单的查询,共执行10000次。首先,我们清空一下SQL Server已经占用的缓存:
dbcc freeproccache然后,执行脚本:
DECLARE @t datetimeSET @t = getdate()SET NOCOUNT ONDECLARE @i INT, @count INT, @sql nvarchar(4000)SET @i = 20000WHILE @i <= 30000BEGIN SET @sql = 'Select @count=count(*) FROM P_Order Where MobileNo = ' + cast( @i as varchar(10) ) EXEC sp_executesql @sql ,N'@count INT OUtpuT', @count OUTPUT SET @i = @i + 1ENDPRINT DATEDIFF( second, @t, current_timestamp
)输出:DBCC 执行完毕。假如 DBCC 输出了错误信息,请与系统管理员联系。
11使用了11秒完成10000次查询。我们看一下SQL Server缓存中所占用的查询计划:Select Count(*) CNT,sum(size_in_bytes) TotalSizeFrom sys.dm_exec_cached_plans查询结果:共有2628条执行计划缓存在SQL Server中。它们所占用的缓存达到:
92172288字节 = 90012KB = 87 MB。我们也可以使用dbcc memorystatus 命令来检查SQL Server的执行缓存和数据缓存占用。执行结果如下:
执行缓存占用了90088KB,有2629个查询计划在缓存里,有1489页空闲内存(每页8KB)可以被数据缓存和其他请求所使用。我们现在修改一下前面的脚本,然后重新执行一下dbcc freeproccache。
再执行一遍修改后的脚本:
DECLARE @t datetimeSET @t = getdate()SET NOCOUNT ONDECLARE @i INT, @count INT, @sql nvarchar(4000)SET @i = 20000WHILE @i <= 30000BEGIN SET @sql = 'select @countcount=count(*) FROM P_Order Where MobileNo = @i' EXEC sp_executesql @sql, N'@count int output, @i int', @count OUTPUT, @i SET @i = @i + 1ENDPRINT DATEDIFF( second, @t, current_timestamp )
输出:DBCC 执行完毕。假如 DBCC 输出了错误信息,请与系统管理员联系。
1即这次只用1秒钟即完成了10000次查询。我们再看一下sys.dm_exec_cached_plans中的查询计划:Select Count(*) CNT,sum(size_in_bytes) TotalSize From sys.dm_exec_cached_plans查询结果:共有4条执行计划被缓存。
它们共占用内存: 172032字节 = 168KB。假如执行dbcc memorystatus,则得到结果:



有12875页空闲内存(每页8KB)可以被数据缓存所使用。到这里,我们已经看到了一个反差相当明显的结果。在现实中,这个例子中的前者,正是经常被使用的一种执行SQL脚本的方式(例如:在程序中通过合并字符串方式拼成一条SQL语句,然后通过ADO.net或者ADO方式传入SQL Server执行)。
解释一下原因:我们知道,SQL语句在执行前首先将被编译并通过查询优化引擎进行优化SQL Server内存占用,从而得到优化后的执行计划,然后按照执行计划被执行。对于整体相似、仅仅是参数不同的SQL语句,SQL Server可以重用执行计划。但对于不同的SQL语句,SQL Server并不能重复使用以前的执行计划,而是需要重新编译出一个新的执行计划。
同时,SQL Server在内存足够使用的情况下,此时并不主动清除以前保存的查询计划(注:对于长时间不再使用的查询计划,SQL Server也会定期清理)。这样,不同的SQL语句执行方式,就将会大大影响SQL Server中存储的查询计划数目。
假如限定了SQL Server更大可用内存,则过多无用的执行计划占用,将导致SQL Server可用内存减少,从而在执行查询时尤其是大的查询时与磁盘发生更多的内存页交换。假如没有限定更大可用内存,则SQL Server由于可用内存减少,从而会占用更多内存。
对此,我们一般可以通过两种方式实现参数化查询:一是尽可能使用存储过程执行SQL语句(这在现实中已经成为SQL Server DBA的一条原则),二是使用sp_executesql 方式执行单个SQL语句(注意不要像上面的之一个例子那样使用sp_executesql)。
在现实的同一个软件系统中,大量的负载类型往往是类似的,所区别的也只是每次传入的具体参数值的不同。所以使用参数化查询是必要和可能的。另外,通过这个例子我们也看到,由于使用了参数化查询,不仅仅是优化了SQL Server内存占用,而且由于能够重复使用前面被编译的执行计划,使后面的执行不需要再次编译,最终执行10000次查询总共只使用了1秒钟时间。
扫描二维码推送至手机访问。
版权声明:本文由2345好导航站长资讯发布,如需转载请注明出处。
Windows 7 64位系统开机后提示"press any key to restart",无法进入系统了,具体现象如下所示: 故障分析: 故障的主要原因还是硬盘的问题,可以先检查是不是接触不良或坏了,进行修复或更换即可。 解决方法: 1、开机按F8不动到高级选项出现在松手,选“...
对于Windows 7系统来说,其默认安装的许多工具是我们很少使用或从来不用的,比如系统自带的扫雷、纸牌游戏等。删除此类长期不用的系统组件,不但可以让系统更清爽,更重要的是还可以提高系统的运行速度,特别是对于硬件配置相对较低的上网本来说,尤其如此。接下来,笔者就给大家介绍一下如何删除Windows...
我一个朋友最近装装了Windows 7,他总感觉有人用了他的电脑,但是一直不确定,他想知道有没有人动用他的电脑,问我有没有办法 我说设置一下就行了: 启动Windows 7,在搜索栏中输入编辑组,马上就搜索到了编辑组策略,点击即可启动程序编辑组策略。依次展开组策略左侧树形列表的计算机配置/管理模...
北京时间1月13日消息,根据计划,微软将于2015年1月13日正式结束对Windows 7SP1的“主流支持”,而这也标志着“扩展支持”阶段的开始,这个阶段将于2020年1月14日结束。 2013年10月份,微软终止销售独立的Windows 7系统安装包,并要求制造商于2014年10月份停止生...
最近小编在使用Windows 7的时侯遇到一个问题,就是应用程序和快捷方式不能锁定到任务栏,我当时不知道怎么回事,但是很多现有的方法都不能解决这个问题。现在我把我的解决的方法分享给大家以作参考。 问题分析 经过思考,初步判断出现该问题的原因是由于使用第三方优化软件消除快捷方式的小箭头引起的。...
经过几天的测试后发现,Windows 7用户反映的情况确实存在,但并没有达到“频繁”的情况。同时,也并非是迅雷或快车抢了带宽。(即便是抢了带宽,表现的形式也是页面打开慢,而非是掉线),寻找问题的原因过程中,我们认为是Windows 7系统对于网卡的电源管理的默认设置造成的。 下面,就以Window...