当心空无一物,它便无边无涯。树在。山在。大地在。岁月在。我在。你还要怎样更好的世界?——张晓风《我在》

为什么要写这个内容?


随着工作经历的积累,越来越感觉到,大量的关系型数据库的性能问题,其根源在于统计信息。这里说的是根源,其实很多时候大家觉得的那些什么索引失效等都只是表象。当然,不能一概而论,还有很多问题如配置问题、设计问题等等,甚至电源也会影响性能。

之所以得出这个结论,因为在常规的开发和部署过程中,一般企业级系统已经大量使用较为高级的磁盘阵列甚至企业级SSD,IO方面的问题已经很少,而且关系数据库的理论发展跟不上硬件发展的速度,所以硬件性能问题带来的系统级别的性能问题已经很少了。

而数据库设计方面的问题,当然也是很重要的,但是对于一个用了几年的系统来说,修修补补也差不多了。

对于编码问题,其实跟索引合起来会比较好,很多时候不是索引有问题,而是你的写法导致了优化器没有用上索引。另外如果是索引问题(没有索引、有索引但没用上、索引过多等),可以看一下我另外两篇索引相关的文章:

1. SQL Server 索引维护(1)——如何获取索引使用情况 http://blog.csdn.net/dba_huangzj/article/details/49735941

2. SQL Server 索引维护(1)——系统常见的索引问题 http://blog.csdn.net/dba_huangzj/article/details/49734963

上面提到的几点相对来说比较容易发现和控制,但是本系列提到的统计信息,由于它很少直接表现出来,而是直接或间接引起其他问题,所以它更加隐秘和难发现。也因此我觉得有必要写这个主题。

总得来说:统计信息就是为了协助数据库管理系统的核心组件之一——性能优化器/查询优化器生成合适的执行计划从而尽可能高效地响应请求。

什么是统计信息


在研究性能问题之前,非常有必要研究统计信息,因为没有统计信息,关系数据库就是个傻子。没有统计信息,优化器往往会使用不合理的假设来生成执行计划从而严重地影响性。

那么数据库需要什么信息呢?首先,要说说数据存储,关系数据库使用块或者页作为最小存储单元,通常是8K/4K大小。也就是说如果你只存储1K的数据,就有7K/3K的空间是浪费的。那么数据库如何知道数据的存储情况以便后期在对 数据库进行维护和使用时能够有一个“可靠”的依据呢?答案当然就是统计信息。

回到统计信息上面,当要求数据库收集统计信息时,它通常会收集这些内容:

  1. 表有多少行/页
  2. 对于表中的每一列,唯一值的长度信息(最长,最短,平均)、数据值的范围(最大,最小,平均)
  3. 表上面的索引信息

这些统计信息可以帮助优化器评估语句可能要使用的CPU、I/O、内存等资源。

同时列上面的统计信息非常重要,比如表A,在关联时用到两个列:firstname和lastname,通过统计信息,数据库知道firstname有1000个不同的值,而lastname有10万个不同的值。因此,在关联时数据库会先关联lastname再关联firstname,因为在lastname中,由于存在大量不同的值,所以列匹配时通常只需要匹配前2~3个字符就足够了。

但是这仅仅是基础统计信息,除此之外还可以让数据库收集其他信息如直方图(histograms),直方图描述列的数据分布情况,比如:

  1. 出现频率最高的值。
  2. 分位数等

准确的统计信息可以协助优化器生成更好的执行计划。特别是有=符号的限定词(如where age=18)。或者范围限定词(where age>18 and age<40。)因为通过统计信息,数据库已经知道这部分数据的分布情况。(专业术语叫选择度 selectivity)。

由于统计信息的重要性,必须实时更新,没有什么比数据库认为一个100万行的表只有500行更糟糕。统计信息唯一的缺点就是需要资源去计算准确的信息。这也是为什么很多数据库管理系统默认不自动更新统计信息的原因。计算几百万数据的信息即使今天也相当困难。所以可以只计算基础统计信息或者计算数据库的一个样本。

比如当你处理几百个都过百万行数据的表时,只计算10%的统计信息可以得益不浅。但是如有可能,还是应该保证统计信息的准确性,因为不准确的统计信息可以把一个30秒的查询变成运行8小时。

SQL Server统计信息简介及环境准备


由于本人一直从事SQLServer工作,所以很不幸,在演示、介绍过程中会以SQL Server为例,但是我尽量接近关系数据库层面而不限于某个产品。同时下一节专门介绍SQLServer统计信息,所以这里只做一个简单的概述:

90%以上的用户关注数据库,除了功能满足要求之外,剩下的关注点无疑就在性能上面。那么如何获得高性能?根源还是在让数据库生成合适的高效的执行计划(如何生成执行计划不在本系列中介绍)。前面提到过,统计信息就是为了协助优化器生成执行计划,准确的、有用的统计信息可以最大限度提供优化器生成高效执行计划所需要的信息(当然这是一个复杂的过程,影响执行计划生成的因素有很多),不准确的统计信息却能把一个秒级查询变成数小时的慢查询。所以统计信息也和索引一样,是一个双刃剑。我们可以把这段话简化成:

查询,烂查询和统计信息

回到SQL Server,当我们需要从数据库中获取数据时,性能是一个关键点(系统异常、故障、逻辑错误在这里不考虑)。SQL Server如果能从数据库中得到准确的有效的关于数据的信息,那么SQLServer在执行数据查询时,就能选择更加高效的方式(表现为执行计划)。而这些信息的关键数据源就是“统计信息”。如果统计信息过时/有误,性能将变得无法接受。

你传给SQL Server的查询首先会传递到SQL Server查询优化器(Query Optimizer)中,如果SQL Server没有缓存执行计划,那么它就会针对这个查询生成一个查询计划。在生成的过程中,SQL Server优化器会 选择与逻辑操作符(如join等)对应的合适的物理操作符在物理层面上进行执行(注:SQL,结构化查询语言,是为了让用户告知数据库需要什么数据或操作,而不是告诉数据库如何去获取数据和操作,所以SQL语言传输到DBMS后需要转换成计算机能识别的操作,这些操作在高层次上看来就是一系列的物理操作符)。在选择物理操作符的时候,一个逻辑操作符可能可以使用多个物理操作符来实现,比如对于逻辑操作符中的WHERE XXX=XXXX,在物理操作符中可能使用索引查找(Index seek)或表扫描(Table Scan)来实现,又比如对于SQL语句中的各种JOIN,可选的物理操作符有Hash、Merge和Nested Loop Joins。

现实世界中,有很多因素会影响优化器对物理操作符的选择,其中最重要的一个就是基数预估(cardinality estimations),这个过程会计算在应用了过滤操作之后,可能剩下的符合条件的行数。不准确的基数预估所生成的执行计划会比准确的执行计划低几个数量级(本人真的见过小时级降到秒级的差距,其原因就是统计信息)。除此之外,这些基数预估还会影响是否进行并行执行、JOIN的顺序,甚至内存分配等一系列的问题。

为了后续演示之用,本系列主要使用SQLServer 2014,自定义一个数据库和测试数据来做演示,如果没有SQL 2014也没关系,这个只影响后面介绍SQL 2014新基数预估的实现而已,本系列中大部分的内容在SQL Server全系列(2000之前的就免了,但是我建议还是以2008 为起点)还是通用的。

本文仅仅是一个简介,对于这里提到的很多东西,会在后面几篇文章里面提到,写好的链接会跟在下面贴出来。

  1. 全废话SQL Server统计信息(2)——统计信息基础

全废话SQL Server统计信息(1)——统计信息简介的更多相关文章

  1. 全废话SQL Server统计信息(2)——统计信息基础

    接上文:http://blog.csdn.net/dba_huangzj/article/details/52835958 我想在大地上画满窗子,让所有习惯黑暗的眼睛都习惯光明--顾城<我是一个 ...

  2. SQL Server 执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变

    前提  本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段 ...

  3. 非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry 大牛

    非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry 大牛 Glenn Berry 大牛会对这个脚本持续更新 -- SQL Server 2012 Diagnost ...

  4. 非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry

    非常全面的SQL Server巡检脚本来自sqlskills团队的Glenn Berry Glenn Berry 曾承诺对这个脚本持续更新 -- SQL Server 2012 Diagnostic ...

  5. SQL Server 虚拟化(1)——虚拟化简介

    本文属于SQL Server虚拟化系列 前言: 现代系统中,虚拟化越来越普遍,如果缺乏对虚拟化工作原理的理解,那么DBA在解决性能问题比如降低资源争用.提高备份还原速度等操作时就会出现盲点.所以基于本 ...

  6. SQL Server 性能优化(一)——简介

    原文:SQL Server 性能优化(一)--简介 一.性能优化的理由: 听起来有点多余,但是还是详细说一下: 1.节省成本:这里的成本不一定是钱,但是基本上可以变相认为是节省钱.性能上去了,本来要投 ...

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

    本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. ...

  8. SQL Server 数据库表的统计信息的更新

             最近在调整基础信息数据时,新增了几个客户类型,意想不到的事情发生了,在使用新增的客户类型作为 查询条件查询报表时,居然出现了超时的现象,但是用其他以前的客户类型查询就没有问题,用一个 ...

  9. sql server实例内存使用统计

    转载于: http://blog.csdn.net/shutao917/article/details/51444424 SQL SERVER内存按存放数据的类型,大概可以分为三类: 1.buffer ...

随机推荐

  1. osx mitmproxy ssl 错误

    记录一下,总是在这里折腾. cd ~ cd .mitmproxy cp mitmproxy-ca-cert.pem ~/ 然后到目录下双击mitmproxy-ca-cert.pem ,在钥匙串中的登录 ...

  2. [POI 2004]SZP

    Description Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工.Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过的特工. ...

  3. [测试题]wows

    Description 山山最近在玩一款游戏叫战舰世界(steam 游戏太少了),他被大舰巨炮的魅力折服,于是山山开了一局游戏,这次发现目标是一艘战列舰新墨西哥级,舰桥很高,原本应该打在目标身后的圆形 ...

  4. 【LSGDOJ1834 Tree】树链剖分

    题目描述 给定一个N个结点的无向树,树中的结点按照1...N编号,树中的边按照1...N − 1编号,每条边都赋予一个权值.你需要编写程序支持以下三种操作: 1.    CHANGE i v:将i号边 ...

  5. NOIP2014-11-3模拟赛

    字符串 题目描述 现在给一个字符串,你要做的就是当这个字符串中存在两个挨着的字符是相同的时就将这两个字符消除.需要注意的是,当把这两个字符消除后,可能又产生一对新的挨着的字符是相同的.比如,初始的字符 ...

  6. UVA12186

    给出一个树状关系图,公司里只有一个老板编号为0,其他人员从1开始编号.除了老板,每个人都有一个直接上司,没有下属的员工成为工人. 工人们想写一份加工资的请愿书,只有当不少于员工的所有下属的T%人递交请 ...

  7. poj 1113 凸包周长

    Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 33888   Accepted: 11544 Descriptio ...

  8. BZOJ4926 皮皮妖的递推

    第二次乱出题.为了方便,以m=2为例,把原式变一下形,得f(i)+f(f(i-1))=i我们先无视掉那个-1,我们发现:诶,这个东西好像斐波那契数列.具体地,我们用f(n)表示把n用斐波那契数列进行拆 ...

  9. flask jQuery ajax 上传文件

    1.html 代码 <div> <form id="uploadForm" enctype="multipart/form-data" > ...

  10. div英文内容超过div长度

    添加css word-break: normal;word-wrap: break-word;