全废话SQL Server统计信息(1)——统计信息简介

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

为什么要写这个内容?

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

之所以得出这个结论,因为在常规的开发和部署过程中,一般企业级系统已经大量使用较为高级的磁盘阵列甚至企业级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)——统计信息基础
时间: 2024-10-03 22:53:56

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

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

接上文:http://blog.csdn.net/dba_huangzj/article/details/52835958 我想在大地上画满窗子,让全部习惯黑暗的眼睛都习惯光明--顾城<我是一个任性的孩子> 这一节主要介绍一些理论层面的东西,主要针对SQL Server,为后面的做铺垫.假设从实操层面考虑能够跳过,可是我强烈建议还是要找时间看一下这节.本节的内容例如以下: SQL Server统计信息 列级统计信息 统计信息与运行计划 统计信息与内存分配 开销预估模型 SQL Server统计

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

前提  本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段的统计信息做数据行数预估的算法原理,以及SQL Server 2012和SQL Server 2014该算法的差异情况, 这里暂时不涉及复合统计信息,暂不涉及统计信息的更新策略及优化相关话题,以及其他SQL Server版本计算方式. 统计信息是什么 简单说就是对某些字段的数据分布的一种描述,让SQ

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

本文属于SQL Server虚拟化系列 前言: 现代系统中,虚拟化越来越普遍,如果缺乏对虚拟化工作原理的理解,那么DBA在解决性能问题比如降低资源争用.提高备份还原速度等操作时就会出现盲点.所以基于本人工作环境的情况和大时代的趋势,同时根据个人经验,绝大部分的IT人员都对虚拟化持有怀疑或者保留意见的态度.所以这里开始一个系列文章,介绍SQL Server虚拟化的内容,内容来自 Stairway to Server Virtualizaion ,如后续有更新或者本人有其他内容,也会添加进去. 目前

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

原文:SQL Server 性能优化(一)--简介 一.性能优化的理由: 听起来有点多余,但是还是详细说一下: 1.节省成本:这里的成本不一定是钱,但是基本上可以变相认为是节省钱.性能上去了,本来要投入的硬件就可以减缓投入,从另外一个角度看来它就是节省了钱. 2.增加效率:对于客户来说,性能上去了,他们的工作效率也高了. 3.降低挫折感:性能底下,客户抱怨,无疑是对自己心灵上的打击. 二.性能误区: 性能误区 误区 现实 如果处理器使用率很高,那么需要添加更快的处理器 某一部分导致了性能问题 8

sql server发生的等待统计信息

SELECT * FROM sys.dm_os_wait_stats WHERE wait_time_ms>0 ORDER BY wait_time_ms DESC 只有sql server重启的时候才会自动清除等待统计信息,可以通过 DBCC SQLPERF("sys.dm_os_wait_stats", CLEAR)命令清除统计信息. 通过一个临时表和waitfor delay 语句跟踪一段时间内发生的变化,从而判断当前正在发生的等待. IF OBJECT_ID('tempd

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

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

SQL Server遍历所有表统计行数

DECLARE CountTableRecords CURSOR READ_ONLY FOR SELECT sst.name, Schema_name(sst.schema_id) FROM sys.tables sst WHERE sst.TYPE = 'U' DECLARE @name VARCHAR(80), @schema VARCHAR(40) OPEN CountTableRecords FETCH NEXT FROM CountTableRecords INTO @name, @s

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

-- SQL Server 2012 Diagnostic Information Queries -- Glenn Berry -- April 2015 -- Last Modified: April 27, 2015 -- http://sqlserverperformance.wordpress.com/ -- http://sqlskills.com/blogs/glenn/ -- Twitter: GlennAlanBerry -- Please listen to my Plura

SQL Server角色成员身份和权限简介

为便于管理数据库中的权限,SQL Server 提供了若干“角色”,这些角色是用于分组其他主体的安全主体.它们类似于 Microsoft Windows 操作系统中的组.数据库级角色的权限作用域为数据库范围.SQL Server 中有两种类型的数据库级角色:数据库中预定义的“固定数据库角色”和您可以创建的“灵活数据库角色”. 固定数据库角色是在数据库级别定义的,并且存在于每个数据库中.db_owner 和 db_securityadmin 数据库角色的成员可以管理固定数据库角色成员身份.但是,只