索引列上的统计 <第一篇>

一、索引在查询优化中的角色

  SQL Server的查询优化器是基于开销的优化器、它通过确认选择性、数据的唯一性以及过滤数据(通过WHERE或JOIN子句)所使用的列来决定最佳的数据访问机制。统计与索引一同存在,但是它们也作为断言的一部分存在于没有索引的列上。

  作为谓词引用的列中数据分布的最新信息帮助优化器确定所使用的查询策略。在SQL Server中,这个信息以统计的形式维护,这对于基于开销的优化器创建一个有效的查询执行计划是很重要的。通过统计,优化器能做出返回结果集或中间结果集所花费时间的精确估计,从而确定最高效的操作。只要确定数据库已经进行了默认的统计设置,优化器就能尽其所能地动态确定有效的处理策略。而且,作为性能问题诊断时的安全性度量,应该确定自动统计维护历程正在按照预想工作。如果有必要,甚至手工控制统计的创建或维护。

二、索引列上的统计

  索引的有效性完全取决于索引列上的统计。如果没有统计,SQL Server的基于开销的查询优化器将不能选择到使用索引最有效的方式。

  SQL Server默认会自动创建索引键的统计,不管它是何时创建的。

  我们知道,随着数据的变化,保持查询低开销的数据检索机制也会变化。例如,如果一个表对于某个列的值的选择性相当高为0.99,那么通过该列上的非聚集索引来检索匹配行是有意义的。但是如果表中数据变化,添加了大量该列有相同值的行选择性下降,那么使用这个非聚集索引就不再有意义。

  SQL Server可以使一个索引上的统计随着索引列内容变化而更新。默认情况下,这个特性被开启,而且可以通过属性=》选项=》数据库的自动更新统计设置来开启或关闭。

  

  更新统计消耗额外的CPU周期。为了优化和更新进行,SQL Server使用如下高效的算法来确定合适的更新统计时机:

  1. 当没有任何行的表得到一个行时;
  2. 当少于500行的表增加500行或更多行时;
  3. 当多于500行的表增加500+20%的行数时;

  这种内建的智能使每个进程的CPU利用率保持很低。也可以异步地更新统计。这意味着当查询正常地导致统计更新时,查询使用旧的统计继续,统计被离线更新。这可以加速一些查询的响应时间,比如在数据库很大或超时间隔很短时。

  可以使用ALTER DATABASE命令手工禁用(或启用)自动更新统计和异步更新统计特性,默认情况下,自动更新统计特性被启用(强烈建议保持启用)。自动异步更新统计特性默认下被禁用,只有确定它能在数据库上对超时有帮助时才开启这一特性。

  1、更新统计的好处以及过时统计的缺点示例

  执行自动更新的好处通常要超过其在系统资源上的开销,自动更新统计能够有效帮助SQL Server查询优化器获得最佳的数据访问途径。

  为了更直接地控制数据的行为,下面来搞个示例实战下,我们有一张Person表,里面有1万条数据左右。

  

  Id列原本是主键,但现在被撤掉了,因此选择性非常高,我们来看看如下SQL语句的执行计划与数据页读取情况:

  

  由执行计划来看,这是一个典型的书签查找,查询返回1条记录,有效地使用了索引。

  

  下面,我们来插入3000条Id为2的记录:

  DECLARE @i int;
  SET @i = 0;
  WHILE (@i < 3000)
  BEGIN
      INSERT INTO PersonTenThousand (Id,PId,Name) VALUES(2,3,‘相同Id号‘)
      SET @i = @i + 1;
  END

  注意:由于SQL Server的索引更新机制,大于500条数据的情况下,插入数量要大于20%的情况下,才会自动更新索引。

  现在再来执行相同的语句以及查询计划:

  

  

  我们看到,由于索引的自动更新机制,执行计划改变了,SQL Server认为对于返回3000条记录,使用表扫描要优于执行3000次书签查找。

  下面,我们来重复一次,先删除原有的3000条Id为2的记录,这次我们先关闭索引统计再插入3000条记录。

  --关闭自动统计索引
  ALTER DATABASE DataExample SET AUTO_UPDATE_STATISTICS OFF

  

  

  我们看到,索引统计的不更新,导致SQL Server仍然使用原来的执行计划,进行了3000多次查找,逻辑读上升。

  这是为什么呢?因为统计不更新了,SQL Server并不知道Id=2多了3000条记录,还是以为Id=2的记录只有一条,因此就使用了索引进行书签查找。

  小结:过时的索引统计会导致SQL Server根据旧的统计执行计划,而实际上这些执行计划在数据更新后可能并不是最优的。因此,最好保持索引的自动更新。

时间: 2024-10-20 08:52:13

索引列上的统计 <第一篇>的相关文章

非索引列上的统计 &lt;第二篇&gt;

非索引列上的统计 有时候,可能在连接或过滤条件中的列上没有索引.即使对这种非索引列,如果查询优化器知道这些列的数据分布(统计),它也很可能做出最佳的选择. 除了索引上的统计,SQL Server可以在没有索引的列上建立统计.即使不是索引列,当你开启了SQL Server自动创建统计功能,SQL Server就自动在执行WHERE.JOIN等查询列上创建统计.数据分布的信息或者特定值出现在非索引列上的可能性,都能够帮助查询优化器确定最优的处理策略.即使查询优化器不能真正使用索引来定位这些列,这也仍

UNIQUEIDENTIFIER列上的统计信息

UNIQUEIDENTIFIER列上的统计信息非常有意思,在它上面有一些很令人讨厌的行为.我们来看下. 问题重现(The repro) 为了向你展示我们刚抱怨的行为,我用下列简单的表定义创建了一个数据库,我在UNIQUEIDENTIFIER列上强制主键约束.这意味着SQL Server在后台会生成唯一聚集索引,聚集索引本身有一个统计信息对象来描述那列的数据分布情况.当然,数据分布是线性的,因为在UNIQUEIDENTIFIER列每个值本身都是唯一的. 1 -- Create a new tabl

Windows系统CPU内存网络性能统计第一篇 内存

最近翻出以前做过的Windows系统性能统计程序,这个程序可以统计系统中的CPU使用情况,内存使用情况以及网络流量.现在将其整理一下(共有三篇),希望对大家有所帮助. 目录如下: 1.<Windows系统CPU内存网络性能统计第一篇 内存> 2.<Windows系统CPU内存网络性能统计第二篇 CPU> 3.<Windows系统CPU内存网络性能统计第三篇网络流量> 本篇将介绍统计系统内存使用情况,包括内存使用率.总物理内存大小.可用物理内存大小.总虚拟内存大小,可用虚

大话企业上云之第一篇

前言: 随着越来越多的企业准备上云, 如何上云,该上什么样的云?已经成为很多企业的一个课题. 一.首先我们需要了解什么是云 百度百科:云是大气中的水蒸气遇冷液化成的小水滴或凝华成的小冰晶,所混合组成的漂浮在空中的可见聚合物. 个人理解:云:提供计算.存储.应用和网络资源. 按照云的部署模式来讲,云可以分为如下三种: 私有云:客户单独部署的,客户拥有这朵云的全部权限 公有云:部署在Internet之上,企业在Internet直接使用该资源,并不拥有公有云基础设施底层的权限,只拥有使用权. 混合云:

SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)

本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. 今天来写一下统计信息对于复合索引在预估时候的计算方法和潜在问题. 本文原形来自于是个实际业务问题,某SQL在利用一个符合索引做查询的时候,发现始终会出现预估误差较大的情况, 而改变复合索引的列顺序,这个预估行数的误差会发生变化, 也就是说,Create  index idx_index1 ON T

Mysql索引优化分析-第一篇

1.性能下降SQL慢 执行时间长 等待时间长 查询语句写的烂 索引失效(单值,复合) 关联查询太多join(设计缺陷或不得已的需求) 服务器调优及各个参数设置(缓冲\线程数等) 2.常见通用的join查询 2.1SQL执行顺序 2.1.1手写 2.1.2机读 2.1.3总结 2.2Join图 2.3建表SQL 2.4 7种Join 3.索引简介 3.1什么是索引 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构. 可以得到索引的本质:索引是数据结构 可以简单

第十二章——SQLServer统计信息(2)——非索引键上统计信息的影响

原文:第十二章--SQLServer统计信息(2)--非索引键上统计信息的影响 前言: 索引对性能方面总是扮演着一个重要的角色,实际上,查询优化器首先检查谓词上的统计信息,然后才决定用什么索引.一般情况下,默认会在创建索引时,索引列上均创建统计信息.但是不代表在非索引键上的统计信息对性能没有用. 如果表上的所有列都有索引,那么将会是数据库负担不起,同时也不是一个好想法,包括谓词中用到的所有列加索引同样也不是好方法.因为索引会带来负载.因为需要空间存放索引,且每个DML语句都会需要更新索引. 一般

Windows系统CPU内存网络性能统计第二篇 CPU CPU整体使用率

分享一下我老师大神的人工智能教程吧.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net 本文配套程序下载地址为:http://download.csdn.net/detail/morewindows/5160810 转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8678359 欢迎关注微博:http://weibo.com/MoreWindo

oracle避免改变索引列的类型

当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换. 假设 EMPNO是一个数值类型的索引列. SELECT … FROM EMP WHERE EMPNO = ‘123’ 实际上,经过ORACLE类型转换, 语句转化为: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123’) 幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. 现在,假设EMP_TYPE是一个字符类型的索引列. SELECT … FROM EMP WHERE