MS SQL 统计信息浅析上篇
统计信息概念
统计信息是一些对象,这些对象包含在表或索引视图中一列或多列中的数据分布有关的统计信息。数据库查询优化器使用这些统计信息来估计查询结果中的基数或行数。 通过这些基数估计,查询优化器可以生成高质量的执行计划。 例如,查询优化器可以使用基数估计选择索引查找运算符而不是耗费更多资源的索引扫描运算符,从而提高查询性能。[参考MSDN]
其实如果你以前没有接触过统计信息,你可以将其看做是数据库为了得到最优的执行计划,统计数据库里面表、索引等对象的一些数据,例如表的记录数、所有列的平均长度、直方图....等一些优化器需要用到的数据信息。SQL查询优化器是一个基于成本的优化器,类似于ORACLE里面的CBO,那么优化器如果要得到成本最低的执行计划,就需要收集获取其生成执行计划的参考依据(统计信息数据)
如果你对这些概念性的东西比较模糊的话,那么为了让你形象的认识一下统计信息,请看下图:
统计信息参数
数据库的统计信息相关参数有三个: 自动创建统计信息(Auto Create Statistics)、自动更新统计信息(Auto Update Statistics)、自动异步更新统计信息(Auto Update Statistics Asynchronously),它们都是数据库级别的。
自动创建统计信息(Auto Create Statistics)
该参数指定数据库是否自动创建缺少的优化统计信息。如果设置为True,则将在优化过程中自动生成优化查询需要但缺少的所有统计信息。当开启自动创建统计信息(Auto Create Statistics)选项时,查询优化器会对在谓词中使用到的列,如果这些列的统计信息不可用或缺少时,则会单独对每列创建统计信息。这些统计信息对创建一个查询计划非常必要。它们创建于那些现有统计对象中不存在直方图的列上,名字包括列名和对象ID的十六进制格式:_WA_Sys_<column_name>_<XXXX>。这些统计信息用于查询优化器决定使用何种优化后的执行计划。
自动更新统计信息(Auto Update Statistics)
该参数指定数据库是否自动更新过期的优化统计信息。如果设置为True,则将在优化过程中自动生成优化查询需要但已过期的所有统计信息。否则不自动更新统计信息。
自动异步更新统计信息(Auto Update Statistics Asynchronously)
如果设置为 True,则启动过期统计信息的自动更新,查询在编译前不会等待统计信息被更新。后续查询将使用可用的已更新统计信息。如果设置为 False,则启动过期统计信息的自动更新的查询将等待,直到更新的统计信息可在查询优化计划中使用。将该选项设置为 True 不会产生任何影响,除非“自动更新统计信息”也设置为 True
关于这三个参数,一般建议开启自动创建统计信息、自动更新统计信息选项,关闭自动异步更新统计信息。
1:对于自动创建统计信息选项,因为统计信息对查询优化器至关重要,没有统计信息,也就失去了它基于成本的优化器的意义,成为无土之木、无源之水。
2:对于自动更新统计信息选项,有时候过期的统计信息会导致严重的性能问题,我都碰到过好几起因为过时统计信息导致SQL查询性能问题的案例,就像错误的地图、错误的导航、错误的指路会让你偏离目的地那样,过时的统计信息往往导致查询优化器选择了次优的执行计划,产生糟糕的性能问题,所以这个参数必须开启。
3:对于自动异步更新统计信息选项,这个选项在OLTP环境下很有用,但在数据仓库中有负面影响。至于是否开启,我建议是关闭。默认也是关闭的。不知道这种观念是否正确。
下面是MSDN给予的使用同步更新统计信息\异步更新统计信息的参考意见:
------------------------------------------------------------------------------------------------------------------------
在以下情况下应考虑使用同步统计信息:
· 您执行会更改数据分布的操作,例如截断表或对很大百分比的行执行大容量更新。如果您在完成该操作后未更新统计信息,则使用同步统计信息将确保对更改的数据执行查询前统计信息是最新的。
在以下情况下,考虑使用异步统计信息来实现可预测性更高的查询响应时间:
· 您的应用程序频繁执行相同的查询、类似的查询或类似的缓存查询计划。与同步统计信息更新相比,使用异步统计信息更新时您的查询响应时间可能具有更高的可预测性,因为查询优化器可以执行传入的查询而不必等待最新的统计信息。这避免延迟某些查询,而不延迟其他查询。有关查找类似查询的详细信息,请参阅使用查询和查询计划哈希值查找和优化类似查询。
· 您的应用程序遇到了客户端请求超时,这些超时是由于一个或多个查询正在等待更新后的统计信息所导致的。在某些情况下,等待同步统计信息可能会导致应用程序因过长超时而失败。
------------------------------------------------------------------------------------------------------------------------
那么先看一下如何通过SQL来查看这三个参数的设置值:
- SELECT name ,
- is_auto_create_stats_on ,
- is_auto_update_stats_async_on ,
- is_auto_close_on
- FROM sys.databases ;
- SELECT CASE WHEN DATABASEPROPERTYEX('DBMonitor', 'IsAutoCreateStatistics') = 1
- THEN 'Yes'
- ELSE 'No'
- END AS 'IsAutoCreateStatistics' ,
- CASE WHEN DATABASEPROPERTYEX('DBMonitor', 'IsAutoUpdateStatistics') = 1
- THEN 'Yes'
- ELSE 'No'
- END AS 'IsAutoUpdateStatistics' ,
- CASE WHEN DATABASEPROPERTYEX('DBMonitor', 'Is_Auto_Update_stats_async_on') = 1
- THEN 'Yes'
- ELSE 'No'
- END AS 'IsAutoUpdateStatsaAyncOn'
- GO
那么这三个参数的值保存在哪里呢?其实只要你稍微花一点心思去研究一下,就会发现其实它是保存在系统表[sys].[sysdbreg]里面,[sys].[sysdbreg]是内部表,默认情况下不可查看,一般你可以通过系统视图sys.database查看和研究其值的出处。
- SET QUOTED_IDENTIFIER ON
- SET ANSI_NULLS ON
- GO
- CREATE VIEW sys.databases AS
- SELECT d.name, d.id AS database_id,
- r.indepid AS source_database_id,
- d.sid AS owner_sid,
- d.crdate AS create_date,
- d.cmptlevel AS compatibility_level,
- convert(sysname, CollationPropertyFromID(p.cid, 'name')) AS collation_name,
- p.user_access, ua.name AS user_access_desc,
- sysconv(bit, d.status & 0x400) AS is_read_only, -- DBR_RDONLY
- sysconv(bit, d.status & 1) AS is_auto_close_on, -- DBR_CLOSE_ON_EXIT
- sysconv(bit, d.status & 0x400000) AS is_auto_shrink_on,-- DBR_AUTOSHRINK
- p.state, st.name AS state_desc,
- sysconv(bit, d.status & 0x200000) AS is_in_standby, -- DBR_STANDBY
- sysconv(bit, d.status & 0x40000000) AS is_cleanly_shutdown, -- DBR_CLEANLY_SHUTDOWN
- sysconv(bit, d.status & 0x80000000) AS is_supplemental_logging_enabled,-- DBR_SUPPLEMENT_LOG
- p.snapshot_isolation_state, si.name AS snapshot_isolation_state_desc,
- sysconv(bit, d.status & 0x800000) AS is_read_committed_snapshot_on,-- DBR_READCOMMITTED_SNAPSHOT
- p.recovery_model, ro.name AS recovery_model_desc,
- p.page_verify_option, pv.name AS page_verify_option_desc,
- sysconv(bit, d.status2 & 0x1000000) AS is_auto_create_stats_on, -- DBR_AUTOCRTSTATS
- sysconv(bit, d.status2 & 0x40000000) AS is_auto_update_stats_on, -- DBR_AUTOUPDSTATS
- sysconv(bit, d.status2 & 0x80000000) AS is_auto_update_stats_async_on, -- DBR_AUTOUPDSTATSASYNC
- sysconv(bit, d.status2 & 0x4000) AS is_ansi_null_default_on, -- DBR_ANSINULLDFLT
- sysconv(bit, d.status2 & 0x4000000) AS is_ansi_nulls_on, -- DBR_ANSINULLS
- sysconv(bit, d.status2 & 0x2000) AS is_ansi_padding_on, -- DBR_ANSIPADDING
- sysconv(bit, d.status2 & 0x10000000) AS is_ansi_warnings_on, -- DBR_ANSIWARNINGS
- sysconv(bit, d.status2 & 0x1000) AS is_arithabort_on, -- DBR_ARITHABORT
- sysconv(bit, d.status2 & 0x10000) AS is_concat_null_yields_null_on, -- DBR_CATNULL
- sysconv(bit, d.status2 & 0x800) AS is_numeric_roundabort_on, -- DBR_NUMEABORT
- sysconv(bit, d.status2 & 0x800000) AS is_quoted_identifier_on, -- DBR_QUOTEDIDENT
- sysconv(bit, d.status2 & 0x20000) AS is_recursive_triggers_on, -- DBR_RECURTRIG
- sysconv(bit, d.status2 & 0x2000000) AS is_cursor_close_on_commit_on, -- DBR_CURSCLOSEONCOM
- sysconv(bit, d.status2 & 0x100000) AS is_local_cursor_default, -- DBR_DEFLOCALCURS
- sysconv(bit, d.status2 & 0x20000000) AS is_fulltext_enabled, -- DBR_FTENABLED
- sysconv(bit, d.status2 & 0x200) AS is_trustworthy_on, -- DBR_TRUSTWORTHY
- sysconv(bit, d.status2 & 0x400) AS is_db_chaining_on, -- DBR_DBCHAINING
- sysconv(bit, d.status2 & 0x08000000) AS is_parameterization_forced, -- DBR_UNIVERSALAUTOPARAM
- sysconv(bit, d.status2 & 64) AS is_master_key_encrypted_by_server, -- DBR_MASTKEY
- sysconv(bit, d.category & 1) AS is_published,
- sysconv(bit, d.category & 2) AS is_subscribed,
- sysconv(bit, d.category & 4) AS is_merge_published,
- sysconv(bit, d.category & 16) AS is_distributor,
- sysconv(bit, d.category & 32) AS is_sync_with_backup,
- d.svcbrkrguid AS service_broker_guid,
- sysconv(bit, case when d.scope = 0 then 1 else 0 end) AS is_broker_enabled,
- p.log_reuse_wait, lr.name AS log_reuse_wait_desc,
- sysconv(bit, d.status2 & 4) AS is_date_correlation_on, -- DBR_DATECORRELATIONOPT
- sysconv(bit, d.category & 64) AS is_cdc_enabled,
- sysconv(bit, d.status2 & 0x100) AS is_encrypted, -- DBR_ENCRYPTION
- sysconv(bit, d.status2 & 0x8) AS is_honor_broker_priority_on -- DBR_HONORBRKPRI
- FROM master.sys.sysdbreg d OUTER APPLY OpenRowset(TABLE DBPROP, d.id) p
- LEFT JOIN sys.syssingleobjrefs r ON r.depid = d.id AND r.class = 96 AND r.depsubid = 0-- SRC_VIEWPOINTDB
- LEFT JOIN sys.syspalvalues st ON st.class = 'DBST' AND st.value = p.state
- LEFT JOIN sys.syspalvalues ua ON ua.class = 'DBUA' AND ua.value = p.user_access
- LEFT JOIN sys.syspalvalues si ON si.class = 'DBSI' AND si.value = p.snapshot_isolation_state
- LEFT JOIN sys.syspalvalues ro ON ro.class = 'DBRO' AND ro.value = p.recovery_model
- LEFT JOIN sys.syspalvalues pv ON pv.class = 'DBPV' AND pv.value = p.page_verify_option
- LEFT JOIN sys.syspalvalues lr ON lr.class = 'LRWT' AND lr.value = p.log_reuse_wait
- WHERE d.id < 0x7fff
- AND has_access('DB', d.id) = 1
- GO
- CREATE TABLE [sys].[sysdbreg]
- (
- [id] [int] NOT NULL ,
- [name] [sys].[sysname] NOT NULL ,
- [sid] [varbinary](85) NULL ,
- [status] [int] NOT NULL ,
- [status2] [int] NOT NULL ,
- [category] [int] NOT NULL ,
- [crdate] [datetime] NOT NULL ,
- [modified] [datetime] NOT NULL ,
- [svcbrkrguid] [uniqueidentifier] NOT NULL ,
- [scope] [int] NOT NULL ,
- [cmptlevel] [tinyint] NOT NULL
- )
- ON[PRIMARY]
- GO
修改统计信息参数
方法1:
----关闭数据库DBMonitor自动创建统计信息功能
USE [master]
GO
ALTER DATABASE [DBMonitor] SET AUTO_CREATE_STATISTICS OFF WITH NO_WAIT
GO
--开启数据库DBMonitor自动创建统计信息功能
USE [master]
GO
ALTER DATABASE [DBMonitor] SET AUTO_CREATE_STATISTICS ON WITH NO_WAIT
GO
--关闭数据库DBMonitor自动更新统计信息功能
USE [master]
GO
ALTER DATABASE [DBMonitor] SET AUTO_UPDATE_STATISTICS OFF WITH NO_WAIT
GO
--启用数据库DBMonitor自动更新统计信息功能
USE [master]
GO
ALTER DATABASE [DBMonitor] SET AUTO_UPDATE_STATISTICS ON WITH NO_WAIT
GO
--关闭数据库DBMonitor自动异步更新统计信息功能
ALTER DATABASE [DBMonitor] SET AUTO_UPDATE_STATISTICS_ASYNC OFF WITH NO_WAIT
GO
--启用数据库DBMonitor自动异步更新统计信息功能
ALTER DATABASE [DBMonitor] SET AUTO_UPDATE_STATISTICS_ASYNC ON WITH NO_WAIT
GO
方法2:使用SP_DBOPTION来启用或禁用。
SP_DBOPTION DBMonitor, 'auto update statistics', 'ON';
SP_DBOPTION DBMonitor, 'auto update statistics', 'OFF;
方法3:图形化方法启用或禁用
对应的图像化操作:选择所要修改的数据库,单击右键选项”属性“,选择左侧的”选项“,则能看到这三个参数
在 AUTO_UPDATE_STATISTICS 为 ON 时,您可以覆盖数据库范围的统计信息更新行为,并且根据您的应用程序的要求为单独的表、索引或列将自动统计信息更新设为关闭。在 AUTO_UPDATE_STATISTICS 为 ON 时,您可以通过以下方式为表、索引或列禁用和重新启用自动统计信息更新:
· 使用 SP_AUTOSTATS 系统存储过程。这可以禁用或重新启用表或索引的统计信息更新。
· 对于 UPDATE STATISTICS 语句指定 NORECOMPUTE 选项。若要重新启用统计信息更新,请重新运行 UPDATE STATISTICS,但不使用
· NORECOMPUTE 选项。
· 对于 CREATE STATISTICS 语句指定 NORECOMPUTE 选项。若要重新启用统计信息更新,请使用 DROP STATISTICS 删除统计信息,然后运行 CREATE STATISTICS 但不使用 NORECOMPUTE 选项。
· 对 CREATE INDEX 语句指定 STATISTICS_NORECOMPUTE 选项。若要重新启用统计信息更新,您可以运行 ALTER INDEX 且 STATISTICS_NORECOMPUTE = OFF。
· 在 AUTO_UPDATE_STATISTICS 为 OFF 时,不能为单独的表、索引或列将自动更新设为打开。重新启用自动统计信息更新将还原AUTO_UPDATE_STATISTICS 选项指定的行为。如果 AUTO_UPDATE_STATISTICS 选项为OFF,统计信息更新将不会发生。
创建统计信息
如何创建统计信息呢,如果选项自动创建统计信息(Auto Create Statistics)开启了,那么数据库会自动创建某些统计信息,另外你也可以通过CREATE STATISTICS 语句手动创建某些统计信息。先看下面的例子:
USE [DBMonitor]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Test]') AND type in (N'U'))
DROP TABLE [dbo].[Test]
GO
SELECT * INTO Test FROM sys.objects;
此时你会看到表Test根本没有统计信息,那么我们在表Test上创建一个索引IDX_TEST_OBJECT_ID
CREATE INDEX IDX_TEST_OBJECT_ID ON dbo.Test(object_id);
此时,你刷新一下表Test的统计信息,你会发现多了一个名为“IDX_TEST_OBJECT_ID”的统计信息,你新建多少条索引,在统计信息下就会创建与索引同名的统计信息。
SELECT DISTINCT TYPE FROM dbo.Test ;
执行上面面脚本后,我刷新统计信息,会发现多了一个名为“_WA_Sys_00000006_023D5A04”的统计信息,截图如下:
那么自动创建统计信息的规律或规则是啥呢?或者理解为:什么时候数据库创建统计信息,其实创建统计信息的规则如下:
1:在索引创建时,SQL SERVER 会自动地在索引所在的列上创建统计信息
2:当SQL SERVER想要使用某些列上的统计信息,发现没有时,SQL SERVER会自动创建统计信息(前提是要开启自动创建统计信息)。例如上面统计DISTINCT TYPE。
3:手工使用CREATE STATISTICS之类的语句手工创建需要的统计信息。
关于CREATE STATISTICS的语法,大家可以参考MSDN,这里不做阐述了。需要注意的是统计信息可以通过全表扫描或随机抽样应读取的数据百分比或指定的数据行数,收集统计信息
更新统计信息
随着数据库的DML操作,数据的变更会导致统计信息过期,那么这时就需要更新统计信息。通常数据库通过两种方式更新统计信息:
1:如果开启了自动更新统计信息(Auto Update Statistics)或自动异步更新统计信息选项,那么数据库会自动更新统计信息。
2:手动更新统计信息
更新统计信息确保查询使用最新的统计信息编译。不过,更新统计信息会导致查询重新编译。我们建议不要太频繁地更新统计信息,因为需要在改进查询计划和重新编译查询所用时间之间权衡性能。此类特定的性能权衡取决于您的应用程序。
那么数据库什么时候、什么条件下才会更新统计信息呢?
1、 在一个空表中有数据的改动。
2、 当统计信息创建时,表的行数只有500或以下,且后来统计对象中的引导列的更改次数大于500.
3、 当表的统计信息收集时,超过了500行,且统计对象的引导列后来更改次数超过500+表总行数的20%时。
4、 在Tempdb中的表,少于6行且最少有6行被更改
注意:数据库不会为表变量收集统计信息,所以数据量比较大时尽量不要使用表变量。
一般建议不要太频繁地更新统计信息,因为需要在改进查询计划和重新编译查询所用时间之间权衡性能。 这种特定的性能权衡取决于您的应用程序。
手工更新统计信息,一般使用 UPDATE STATISTICS 或存储过程 sp_updatestats 来更新统计信息。
sp_autostats:显示或更改特定索引或统计信息的自动 UPDATE STATISTICS 设置,或者显示和更改当前数据库中指定表或索引视图的所有索引和统计信息的自动 UPDATE STATISTICS 设置
显示表的所有索引的当前状态
USE DBMonitor;
GO
EXEC sp_autostats 'dbo.test';
启用表的所有索引的自动统计信息
USE DBMonitor;
GO
EXEC sp_autostats 'dbo.test','ON'
禁用特定索引的自动统计信息
USE DBMonitor;
GO
EXEC sp_autostats 'dbo.test','OFF', 'IDX_TEST_OBJECT_ID';
查看统计信息
如果要了解具体的统计信息内容,那么我们首先要知道如何查看具体的统计信息,统计信息保存在那些系统视图里面,如果能很好的回答这两个问题,那么我想你也就能知道统计信息的具体内容是那些了。关于第二个问题,后面章节部分再做探讨。
查看统计信息,我们先由浅入深,由简单到复杂。
sp_helpstats :返回指定表中列和索引的统计信息。
USE DBMonitor;
GO
EXEC sp_helpstats 'test' ,'ALL'
下面我们看看sys.sp_helpstats的脚本
SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GO CREATE PROCEDURE sys.sp_helpstats
@objname NVARCHAR(776) , -- the table to check for statistics
@results NVARCHAR(5) = 'STATS' -- 'ALL' returns indexes & stats, 'STATS' returns just stats
AS -- PRELIM SET nocount ON DECLARE @objid INT , -- the object id of the table
@indid SMALLINT , -- the index id of an index
@indname SYSNAME ,
@keys NVARCHAR(2078) ,-- string build index key list, length = (16*max_id_length)+(15*2)
@dbname SYSNAME ,
@i INT ,
@thiskey SYSNAME ,
@curs CURSOR -- Check to see that the object names are local to the current database. SELECT @dbname = PARSENAME(@objname, 3) IF @dbname IS NULL
SELECT @dbname = DB_NAME() ELSE
IF @dbname <> DB_NAME()
BEGIN RAISERROR(15250,-1,-1) RETURN (1) END -- Check to see the the table exists and initialize @objid. SELECT @objid = OBJECT_ID(@objname, 'local') IF @objid IS NULL
BEGIN RAISERROR(15009,-1,-1,@objname,@dbname) RETURN (1) END IF UPPER(@results) <> 'STATS'
AND UPPER(@results) <> 'ALL'
BEGIN RAISERROR(N'Invalid option: %s', 1, 1, @results) RETURN (1) END IF UPPER(@results) = 'STATS'
BEGIN SET @curs = cursor local fast_forward READ_ONLY for select stats_id, name from sys.stats where object_id = @objid and IndexProperty(@objid, name, 'IsStatistics') = 1 -- User created & auto-created stats END ELSE
BEGIN SET @curs = cursor local fast_forward READ_ONLY for select stats_id, name from sys.stats where object_id = @objid -- Indexes, User created & auto-created stats END OPEN @curs FETCH @curs INTO @indid, @indname -- IF NO STATISTICS, QUIT IF @@fetch_status < 0
BEGIN DEALLOCATE @curs IF UPPER(@results) = 'STATS'
BEGIN RAISERROR(15574,-1,-1) --'Object does not have any statistics.' END ELSE
BEGIN RAISERROR(15575,-1,-1) --'Object does not have any indexes or statistics.' END RETURN (0) END -- create temp table CREATE TABLE #spstattab
(
stats_name SYSNAME COLLATE database_default
NOT NULL ,
stats_keys NVARCHAR(2078) COLLATE database_default
NOT NULL
) -- Now check out each statistics set, figure out its keys and -- save the info in a temporary table that we'll print out at the end. WHILE @@fetch_status >= 0
BEGIN -- First we'll figure out what the keys are. SELECT @keys = INDEX_COL(@objname, @indid, 1) ,
@i = 2 ,
@thiskey = INDEX_COL(@objname, @indid, 2) WHILE ( @thiskey IS NOT NULL )
BEGIN SELECT @keys = @keys + ', ' + @thiskey ,
@i = @i + 1 SELECT @thiskey = INDEX_COL(@objname, @indid, @i) END -- INSERT ROW FOR INDEX INSERT INTO #spstattab
VALUES ( @indname, @keys ) -- Next index FETCH @curs INTO @indid, @indname END DEALLOCATE @curs -- DISPLAY THE RESULTS SELECT 'statistics_name' = stats_name ,
'statistics_keys' = stats_keys
FROM #spstattab
ORDER BY stats_name RETURN (0) -- sp_helpstats ----------------------- sp_helptext ---------------------------------------- RAISERROR(15339,-1,-1,'sys.sp_helptext') GO
2:查看统计信息一般用DBCC SHOW_STATISTICS命令,如下所示
DBCC SHOW_STATISTICS('TEST', 'IDX_TEST_OBJECT_ID'); Name Updated Rows Rows Sampled Steps Density Average key length String Index Filter Expression Unfiltered Rows
------------------------------------------------- ------------------
IDX_TEST_OBJECT_ID 09 24 2013 9:06PM 59 59 41 1 4 NO NULL 59 (1 行受影响) All density Average Length Columns
------------- -------------- ---------------------------------------
0.01694915 4 object_id (1 行受影响) RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
------------ ------------- ------------- -------------------- --------------
0 1 0 1
1 1 1 1
0 1 0 1
0 1 0 1
0 1 0 1
0 1 0 1
1 1 1 1
1 1 1 1
0 1 0 1
0 1 0 1
0 1 0 1
0 1 0 1
0 1 0 1
1 1 1 1
0 1 0 1
0 1 0 1
0 1 0 1
1 1 1 1
0 1 0 1
0 1 0 1
2 1 2 1
2 1 2 1
1 1 1 1
0 1 0 1
0 1 0 1
0 1 0 1
0 1 0 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
0 1 0 1
0 1 0 1
1 1 1 1
0 1 0 1
1 1 1 1
1 1 1 1
1 1 1 1
0 1 0 1
0 1 0 1
0 1 0 1 (41 行受影响) DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
虽然查看统计信息很容易,但是要读懂并能读取一些信息那们就不是那么简单的了。
列名 |
描述说明 |
Name |
统计信息对象名称 |
Update |
上一次更新统计信息的日期和时间 |
Rows |
在目标索引、统计信息或列中的总行数。如果筛选索引或统计信息,此行数可能小于表的行数。 |
Rows Sampled |
用于统计信息计算的抽样总行数。 |
Steps |
统计信息对象第一个键列的直方图中的值范围数。每个步骤包括在直方图结果中定义的 RANGE_ROWS 和 EQ_ROWS。 |
Density |
查询优化器不使用此值。显示此值的唯一目的是为了向后兼容。密度的计算公式为 1 / distinct rows,其中 distinct rows 是直方图输出中所有步骤的 DISTINCT_RANGE_ROWS 之和。如果对行进行抽样,distinct rows 则基于抽样行的直方图值。 |
Average Key Length |
统计信息对象的键列中,所有抽样值中的每个值的平均字节数 |
String Index |
如果为“是”,则统计信息中包含字符串摘要索引,以支持为 LIKE 条件估算结果集大小。仅当第一个键列的数据类型为char、varchar、nchar、nvarchar、varchar(max)、nvarchar(max)、text 或 ntext 时,才会对此键列创建字符串索引。 |
Filter Expression |
包含在统计信息对象中的表行子集的表达式。NULL = 未筛选的统计信息。有关详细信息,请参阅筛选统计信息。 |
Unfiltered Rows |
应用筛选器表达式前表中的总行数。如果 Filter Expression 为 NULL,Unfiltered Rows 等于行标题值。 |
下表对指定 DENSITY_VECTOR 时结果集中所返回的列进行了说明。
列名 |
说明 |
All Density |
针对统计信息对象中的列的每个前缀计算密度(1/ distinct_rows)。密度包含所有抽样行中的非重复行,包括带有直方图边界点的行。结果为每个密度显示一行。例如,如果统计信息对象包含键列 (A, B, C),结果将报告 (A)、(A,B) 以及 (A, B, C) 的密度。非重复行具有一个不同的列值向量。对于列 (A,B,C),两个不同的向量值的示例为 (4,5,6) 和 (4,5,7)。对于 (A,B),相同的两行具有一个不同的向量值 (4,5)。对于 (A),存在一个不同的值 (4)。 |
Average Length |
每个列前缀的列值向量的平均长度(按字节计)。例如,如果列前缀为列 A 和 B,则长度为列 A 和列 B 的字节之和。 |
Columns |
为其显示 All density 和 Average length 的前缀中的列的名称。 |
下表对指定 HISTOGRAM 选项时结果集中所返回的列进行了说明。
列名 |
说明 |
RANGE_HI_KEY |
直方图步骤的上限值。 |
RANGE_ROWS |
表中位于直方图步骤内(不包括上限)的行的估算数目。 |
EQ_ROWS |
表中值与直方图步骤的上限值相等的行的估算数目。 |
DISTINCT_RANGE_ROWS |
直方图步骤内(不包括上限)非重复值的估算数目。 |
AVG_RANGE_ROWS |
直方图步骤内(不包括上限)重复值的频率或平均数目(如果 DISTINCT_RANGE_ROWS > 0,则为 RANGE_ROWS / DISTINCT_RANGE_ROWS)。 |
统计直方图用作在查询执行计划中查询优化器的选择依据
图形化查看
删除统计信息
DROP STATISTICS 删除当前数据库的指定表中的多个集合的统计信息。
DROP STATISTICS Test._WA_Sys_00000006_023D5A04;
需要注意的是不能用DROP STATISTICS 删除有关索引的统计信息。统计信息的保留时间与索引存在的时间相同,当你删除索引时,对应的统计信息也自动删除。如下所示:
DROP STATISTICS Test.IDX_TEST_OBJECT_ID
消息 3739,级别 11,状态 1,第 1 行
无法对索引 'Test.IDX_TEST_OBJECT_ID' 执行 DROP,因为该索引不是统计信息集合。
参考资料:
http://technet.microsoft.com/zh-cn/library/ms190397(v=sql.105).aspx
http://technet.microsoft.com/zh-cn/library/ms187348.aspx
http://blog.csdn.net/dba_huangzj/article/details/8041267
http://blog.csdn.net/zhaowenzhong/article/details/6276878
MS SQL 统计信息浅析上篇的更多相关文章
- MS SQL统计信息浅析下篇
MS SQL统计信息浅析上篇对SQL SERVER 数据库统计信息做了一个整体的介绍,随着我对数据库统计信息的不断认识.理解,于是有了MS SQL统计信息浅析下篇. 下面是我对SQL Serve ...
- SQL统计信息解释
[SQL基础]统计信息解释 在平时优化SQL的时候,最长用的就是:SET STATISTICS ON,它可以用来查看我们写的查询语句到底性能如何,不过,究竟这个性能的指标是怎么样的呢?首先需要明白的, ...
- Insert插入不同的列数量,统计信息对比
一.实验目的: Insert插入表中相同的行数量,不同的列数量,通过10046 和autotrace工具对比查看逻辑读.物理读.time数据,并得出相应结论 二.测试 2.1测试流程: =>[为 ...
- SQL Server统计信息偏差影响表联结方式案例浅析
我们知道数据库中的统计信息的准确性是非常重要的.它会影响执行计划.一直想写一篇关于统计信息影响执行计划的相关博客,但是都卡在如何构造一个合适的例子上,所以一直拖着没有写.巧合,最近在生产环境中遇到 ...
- SQL Server信息偏差影响表联结方式统计
SQL Server统计信息偏差影响表联结方式案例浅析 我们知道数据库中的统计信息的准确性是非常重要的.它会影响执行计划.一直想写一篇关于统计信息影响执行计划的相关博客,但是都卡在如何构造一个合适 ...
- SQL Server 统计信息更新时采样百分比对数据预估准确性的影响
为什么要写统计信息 最近看到园子里有人写统计信息,楼主也来凑热闹. 话说经常做数据库的,尤其是做开发的或者优化的,统计信息造成的性能问题应该说是司空见惯. 当然解决办法也并非一成不变,“一招鲜吃遍天” ...
- SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)
本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. ...
- SQL Server2016 新功能实时查询统计信息
SQL Server2016 新功能实时查询统计信息 很多时候有这样的场景,开发抱怨DBA没有调优好数据库,DBA抱怨开发写的程序代码差,因此,DBA和开发都成为了死对头,无法真正排查问题. DBA只 ...
- 通过手动创建统计信息优化sql查询性能案例
本质原因在于:SQL Server 统计信息只包含复合索引的第一个列的信息,而不包含复合索引数据组合的信息 来源于工作中的一个实际问题, 这里是组合列数据不均匀导致查询无法预估数据行数,从而导致无法选 ...
随机推荐
- SQL SERVER 通用分页存储过程,两种用法任你选
写在前面 从SQLSERVER 2005开始,提供了Row_Number()函数,利用函数生成的Index来处理分页,按照正常的逻辑思维都是传pageIndex和pageSize来完成分页,昨天前端和 ...
- 使用idea debug多线程
最近采用hystrix远程访问webservice, 遇到一个重定向303的exception,想要debug一下,发现打了断点后总是被跳过.想到hystrix异步线程的问题,于是想要debug就得支 ...
- AngularJS----服务,表单,模块
AngularJS中的服务 服务是一个函数或对象,AngularJS中可以创建自己的服务或使用内建服务.$http是AngularJS中最常见的服务,服务向服务器发送请求,应用响应服务器传送过来的数据 ...
- 一个简单的后台与数据库交互的登录与注册[sql注入处理,以及MD5加密]
一.工具: vs2013[因为我现在用的也是2013,版本随便你自己开心] sql2008[准备过久升级] 二.用到的语言: HTML+CSS+Jquery+Ajax+sqlserver HTML[相 ...
- Xamarin android 之Activity详解
序言: 上篇大概的讲解了新建一个android的流程.今天为大家带来的是Activity详解,因为自己在开发过程中就遇到 好几次坑,尴尬. 生命周期 和Java里头一样一样的,如图 图片来源于网上哈, ...
- 疯狂Android讲义 - 学习笔记(八)
第10章 Service与BroadcastReceiver 10.1 Service简介 Service组件也是可执行的程序,有自己的生命周期,创建.配置Service与创建.配置Activity的 ...
- 疯狂Android讲义 - 学习笔记(五)
第五章 Android使用统一的Intent对象来封装“启动意图”,不管是启动Activity.Service组件.或者BroadcastReceiver等,提供了一致的编程模型.Intent设计有点 ...
- java静态方法调用&&构造函数&&静态块
静态方法,也就是使用static声明的方法,在虚拟机启动加载类的时候就进行了创建,所以使用到静态方法时,直接使用类名点静态方法即可调用.java在执行静态方法前,不会调用构造函数:构造函数是在实例化j ...
- phpstorm 软件
PhpStorm是一款强大的IDE,非常适合于PHP开发人员及前端工程师.提供诸于:智能HTML/CSS/JavaScript/PHP编辑.代码质量分析.版本控制集成(SVN.GIT).调试和测试等功 ...
- 轻量的、可自定义 CSS 的 Lightbox 相册插件
jQuery LightGallery是一个轻量级的,可定制的,模块化的,响应式的 jQuery 相册插件.它采用 CSS 来实现图像和视频的大小调整.因此,这将是非常灵活的,并且比使用 JavaSc ...