经过一系列的Insert/Update/Delete后,统计信息可能不会是最新。如果SQL Server查询优化器在表里需要指定列的统计信息,自上次统计信息创建或更新后经历了实质的更新活动,SQL Server会通过采样列值自动更新统计信息(通过自动更新统计信息)。统计信息的自动更新由查询优化器或编译好的计划执行来触发,它只涉及到查询里引用到的各个列。如果自动异步更新统计信息是停用的话,统计信息会在查询编译前更新,启用的话是在查询编译后更新。当统计信息是异步更新时,受益于触发更新的查询使用老的统计信息。对一些工作量来说,这可以提供更可预估的响应时间,尤其是那些大表上的短时间运行的查询。

当一个查询首次编译完成,如果优化器需要指定对象的统计信息,这个统计信息存在的话,若已过期则自动更新统计信息。如果一个查询被执行且它的计划在缓存里,计划依赖的统计信息会被检查是否过期,如果过期,计划会在缓冲中移除,在查询的重编译时,统计信息会被更新。如果计划依赖的任何统计信息被更新的话,计划都会从缓存中移除。

SQL Server 2008基于列修改的计数器(colmodctrs)来决定是否更新统计信息:

在下列情况下,统计信息对象被认为过期:

如果在常规表上定义的统计信息,被认为过期的话,那么:

  1. 表的大小从0行变成了大于0行(测试1)
  2. 当统计信息收集时,表的行数为500或更少,统计的第一列对象的计数器,自改变为大于500时(测试2)。
  3. 当统计信息收集时,表的行数大于500时,统计的第一列对象的计数器,受表里超过500 +20%的行数而改变(测试3)。

上述描述来自微软的MSDN,具体参见Statistics Used by the Query Optimizer in Microsoft SQL Server 2008。

前2个条件还是相当好的,但第3个条件在处理大表时,有些时候阀值会很高,但对统计信息更新还是无效。例如有个表有100000条记录,只有在200500条件记录被修改后(update/insert),对于触发自动更新还是无效的阀值。

我们来看个例子。

1 USE StatisticsDB
2 GO
3
4 DROP TABLE SalesOrderDetail
5 SELECT * INTO SalesOrderDetail FROM AdventureWorks2008r2.sales.SalesOrderDetail
6 CREATE INDEX ix_ProductID ON SalesOrderDetail(ProductID)
7 SET STATISTICS IO ON
8 SELECT * FROM SalesOrderDetail WHERE ProductID=725

我们创建了SalesOrderDetail表的副本,并在上面创建非聚集索引,我们看下最后SELECT查询的执行计划,点击工具栏的显示包含实际的执行计划。

优化器选择了索引查找和书签查找操作作为优化的计划,完成这个操作需要377个逻辑读。

salesOrderDetail 表有121317条记录,上述第3个条件如果要使统计信息无效的话,121317的20% =24263+500=24763条记录需要被修改,我们用下列语句只更新5000条记录,再次看看查询的执行计划,点击工具栏的显示包含实际的执行计划。

1 SET ROWCOUNT 5000
2 UPDATE SalesOrderDetail SET ProductID=725 WHERE ProductID<>725
3 SET ROWCOUNT 0
4 SET STATISTICS IO ON
5 SELECT * FROM SalesOrderDetail WHERE ProductID=725

执行计划里估计行数是374,这是基于上次更新操作收集的统计信息。优化器基于统计信息,选择了索引查找和书签查找作为最优计划。SELECT操作进行5390逻辑读来完成这个操作。

下一步,我们用producid值为725来更新19762条记录。实际上我们更新24762条记录(包含上一步5000条更新的记录),比使统计信息无效的更新的记录(24763)少1条。

1 SET ROWCOUNT 19762
2 UPDATE SalesOrderDetail SET ProductID=725 WHERE ProductID<>725
3 SET ROWCOUNT 0
4 SET STATISTICS IO ON
5 SELECT * FROM SalesOrderDetail WHERE ProductID=725

执行计划里估计行数是374,这是基于上次更新操作收集的统计信息。优化器基于统计信息,选择了索引查找和书签查找作为最优计划。完成这个操作需要25206个逻辑读。

现在我们更新再多一条记录使统计信息无效。

1 SET ROWCOUNT 1
2 UPDATE SalesOrderDetail SET ProductID=725 WHERE ProductID<>725
3 SET ROWCOUNT 0
4 SET STATISTICS IO ON
5 SELECT * FROM SalesOrderDetail WHERE ProductID=725

(这里我跌了个跟头,在SQL SERVER 2008R2里首次执行,始终是下列结果:

回家吃饭还在思考这个问题,一想原因,应该是自动创建统计信息和自动更新统计信息被停用的原因(上篇文章理解统计信息(3/6):谁创建和管理统计信息?在性能调优中,统计信息的作用 代码执行后未还原为默认设置),在数据库属性里一看,果然是False状态,赶紧用下列语句启用,出现的问题立马消失!

1 ALTER DATABASE StatisticsDB SET AUTO_CREATE_STATISTICS ON
2 ALTER DATABASE StatisticsDB SET AUTO_UPDATE_STATISTICS ON

看来计算机是最诚实可靠的,即使计算机犯了错,也是因为人犯错造成的! )

和我们预期的一样,SELECT语句触发了自动更新统计信息,计划中的估计行数和实际行数已经非常接近了。这可以帮助优化器选择更好的执行计划。优化器选择了表扫描而不是索引查找和书签查找。SELECT操作只进行了1495个逻辑读来选取25137条记录,比起25212个逻辑读才选择2516条记录。在第一步,我们只更新了5000条记录,如果统计信息在那个时候更新的话,优化器可能会选择表扫描作为最优计划而不是索引查找和书签查找。那样的话就可以只用1495个逻辑读代替5390个逻辑读来完成操作,这样就会好很多。

从这个例子我们可以清楚看到,对于自动更新统计信息的阀值对于获得最优性能还是不够好。对于大表来说会更糟。我们就需要人为去更新统计信息用来保证长须的最佳性能,当然更新的频率要看具体的工作量。

在进行大量DML操作后,统计信息都会过期,在查询计划访问统计信息前,统计信息都不会自动更新。更清楚的说,SQL Server会在下列情况自动更新统计信息:

  • 查询第一次编译,计划使用到的统计信息已经过期
  • 查询已有存在的查询计划,但计划中的统计信息已经过期。
本文转自Woodytu博客园博客,原文链接:http://www.cnblogs.com/woodytu/p/4521590.html,如需转载请自行联系原作者

自动更新统计信息的阀值——人为更新统计信息的重要性相关推荐

  1. 更新SQL Server实例所有数据库表统计信息

    引出问题 自从上次菜鸟为老鸟解决了<RDS SQL SERVER 解决中文乱码问题>问题,老鸟意犹未尽,决定再想个招来刁难刁难菜鸟:"我最近做T-SQL性能调优的时候,经常发现执 ...

  2. 无尽的任务1-仿CNZZ的流量统计,完成80%(更新1次)

    终于到周末了 ,任务也快接近尾声了,这次要写的流量统计,其实思路很简单,只是一些细节问题花掉了不少时间,对于采集各个浏览器的得到的关健词的乱码问题花的时间最多,换了几种思路. 现在先来简单介绍一下,任 ...

  3. 史上最全的iOS各种设备信息获取总结(iPhone X 详细信息已更新)

    2016.07.01 更新至iPhone X 新增设备颜色的获取 为了统计用户信息.下发广告,服务器端往往需要手机用户设备及app的各种信息,下面讲述一下各种信息的获取方式: 点击下载以上展示效果的G ...

  4. wxpython后台如何更新界面信息_wxpython后台线程更新界面控件方法

    在大多数的GUI应用程序中,在应用程序的后台中长期执行一个处理过程而不干涉用户与应用程序的其它部分的交互是有好处的.允许后台处理的机制通常是产生一个线程并在该线程中长期执行一个处理过程.对于wxPyt ...

  5. 2017校招信息每日汇总(更新至8.4)

    2017校招信息每日汇总(更新至8.4) 2016-07-25 18:24:05 校招攻略 [想获取内推方式请在APP客户端评论区留邮箱,我们会邮件联系你] U料内推群: 2017秋季校招内推2群 Q ...

  6. 2010年全球地震统计 4月14日 更新

    2010年全球地震统计 4月14日 更新 2010年4月14日 中国地震台网中心消息,北京时间2010年4月14日09时25分许,青海省玉树藏族自治州玉树县(北纬33.2°,东经96.6°)发生6.3 ...

  7. Boost:计算一些tail统计数据,插入数据,更新数据

    Boost:计算一些tail统计数据,插入数据,更新数据 实现功能 C++实现代码 实现功能 计算一些tail统计数据,插入数据,更新数据 C++实现代码 #include <iostream& ...

  8. 不会自动更新了_手机老是自动更新系统?不想频繁更新,不同手机怎么设置好?...

    手机换代快,相应的手机系统更新也很快.由于很多手机会自动更新系统,这个是很方便的.但如果我们不想更新系统,怎么关闭阻止系统更新呢?小移教你几招~ 小米 小米手机,在用的系统版本很顺手,感觉没必要频繁更 ...

  9. 微信快速开发框架(八)-- V2.3--增加语音识别及网页获取用户信息,代码已更新至Github...

    不知不觉,版本以每周更新一次的脚步进行着,接下来应该是重构我的代码及框架的结构,有朋友反应代码有点乱,确实如此,当时写的时候只是按照订阅号来写的,后来才慢慢增加到支持API接口.目前还在开发第三方微信 ...

最新文章

  1. Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解(每日训练 Day.16 )
  2. Java程序员总结分布式架构,你又了解多少呢?
  3. flutter开发vscode插件推荐(开发必备)
  4. 由于html元素加载导致的问题
  5. Android 数据存储之文件存储小记
  6. 详解数据治理相关的7个术语和名词
  7. matlab2c使用c++实现matlab函数系列教程-var函数
  8. android学习之ListView如何使用
  9. 关于逻辑或的一个小小应用注意点
  10. 【POJ 3320】【尺取法】Jessica's Reading Problem【暑期 No.2】
  11. Nero Burning Rom V6多区段刻录详解
  12. 分销渠道都有哪些策略
  13. Linux 打包压缩(tar、gzip、bzip、xz)备份(备份dump genisoimage 还原restore)
  14. 《深入浅出图神经网络》
  15. 小程序进度条_【好玩的游戏大全】我的煎饼屋:好玩的摆摊微信小游戏小程序...
  16. 09Apache POI学习笔记
  17. 微信小程序海报画布生成圆形头像
  18. 学院新闻报道,邹老师光临指导
  19. append和extend的差别
  20. 国外免费公共DNS解析服务器

热门文章

  1. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
  2. 十进制数转N进制c++实现
  3. CalendarDemo Calendar 类的创建及用法
  4. WIZnet推出串口转以太网模块WIZ550S2E
  5. db link的查看创建与删除
  6. 数据库性能Quest Performance Analysis Overview
  7. What's new in C# from 2.0 to 5.0
  8. POJ 3984 迷宫问题 (Dijkstra)
  9. 视觉slam学习笔记以及课后习题《第三讲李群李代数》
  10. 相机标定(四)—— 仿射变换和透视变换