密度向量

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

在日常生活中,我们用统计信息来采取决定。SQL Server优化器也用同样的方式,使用统计信息来选择正确的执行计划。如果统计信息错误或过期,SQL Server可能就会选择错误的执行计划。在这个文章里,我们换个方式理解下统计信息。

查询优化器使用统计信息来判断每一步返回的行。执行计划里的估计行数信息是基于列的可用统计信息计算而来的。统计信息给我们列里数据分布情况。没有统计信息,查询优化器不能够判断不同计划的效率。通过使用统计信息,查询优化器在访问数据时可以做出正确的选择。

在我们定义索引时,统计信息会自动创建。除此之外,当列在查询里被引用,作为WHERE条件的一部分,在group by子句里或join条件里,统计信息都会创建。为了自动创建统计信息,在数据库层里的AUTO_CREATE_STATISTICS 设置应该被启用。默认情况下这个设置是被启用的。除此之外,统计信息可以使用CREATE STATISTICS命令创建。

在SQL Server里存储的统计数字是关于密度向量和直方图(数据分布)的信息。在我们讨论更多细节前,先理解这2个概念。

密度向量:在给出列或一组列唯一值的比例。统计密度向量的公式:1/列(或一组列)不同值个数。

密度向量用来衡量列的唯一性或列的选择性。密度向量的值在0和1之间。如果这列的密度值为1,表示这列的所有记录值一样,选择性低。更高的密度带来更低的选择性。如果这列的密度值为0.003,表示这列有1/0.003=333个不同值。

我们来看个例子,用下列语句创建表并在上面建立2个索引。 

复制代码
1 USE StatisticsDB
2 GO
3 
4 SELECT * INTO SalesOrderDetail FROM AdventureWorks2008R2.Sales.SalesOrderDetail
5 CREATE UNIQUE CLUSTERED INDEX ix_SalesOrderDetailID ON SalesOrderDetail(SalesOrderDetailID)
6 CREATE NONCLUSTERED INDEX ix_productid ON SalesOrderDetail(productid)
复制代码

我们来看看这2个索引的统计信息。

1 DBCC SHOW_STATISTICS('dbo.SalesOrderDetail', 'ix_SalesOrderDetailID')

输出结果有3个表,分别是:统计信息头,密度向量和直方图。

在第1部分(统计信息头)

  • Name :索引名称
  • Updated :统计信息更新时间
  • Rows :索引里行数目。不是表里的行数。
  • Rows Sampled :用于生成统计信息的采样行数。创建索引的时候,会进行完全扫描。
  • Steps :直方图里的步长。(第3部分的内容)
  • Density :在SQL Server里不再使用,向老版本兼容。
  • Average key length :索引键平均长度。
  • String Index :用于like时估计统计行数。
  • Filter Expression :过滤索引表达式
  • Unfiltered Rows :未过滤的行数,如果不存在过滤索引,则等同于Row列。

可以使用DBCC SHOW_STATISTICS加WITH STAT_HEADER来只获取统计头信息。

在第2部分的密度表,我们只看到一条记录,因为在我们索引里只有1列。

所有密度列给我们SalesOrderDetailsId 列的密度值(1/列(或一组列)不同值个数)。所有密度列给我们值 8.242868E-06 =0.000008242868。这表示SalesOrderDetailsId 列有 1/0.000008242868=121317个唯一值,我们可以用下列语句验证下。

1 SELECT COUNT(DISTINCT SalesOrderDetailID ) FROM SalesOrderDetail

可以使用DBCC SHOW_STATISTICS加WITH DENSITY_VECTOR来只获取密度向量信息。

我们来看看非聚集索引ix_productid的密度。

1 DBCC SHOW_STATISTICS('dbo.SalesOrderDetail', 'ix_productid') WITH DENSITY_VECTOR

在密度表里可以看到2行记录,即使我们的非聚集索引是在单列上。这是因为聚集键是非聚集索引的一部分(参见索引深入浅出(4/10):非聚集索引的B树结构在聚集表)。

第一行告诉我们,ProductID 列的密度向量值为0.003759399,换句话说,在ProductID列有1/0.003759399=226个唯一值。我们可以验证下。

1 SELECT COUNT(DISTINCT ProductID) FROM dbo.SalesOrderDetail

第二行告诉我们,ProductID和SalesOrderDetailID组合列的密度向量值是0.000008242868,换句话说,ProductID和SalesOrderDetailID组合列有121317个唯一值,这个和表的总记录数是一致的。

密度向量值会用在哪里呢,我们看下下面查询的执行计划,点击工具栏的显示包含实际的执行计划。

1 SELECT ProductID,COUNT(*) FROM dbo.SalesOrderDetail GROUP BY ProductID

 

在执行计划里,在流聚合运算符的输出里,我们看到估计行数是266。在ProductID列唯一值(个数)可以从密度表里拿到。但我们怎么证明查询优化器是用这个值来计算估计行数。我们创建另外一个没有任何索引的SalesOrderDetail表。

1 SELECT * INTO SalesOrderDetail_NoStats FROM SalesOrderDetail

通过下面语句我们可以看出,这表没有任何的统计信息。

1 EXEC SP_HELPSTATS 'SalesOrderDetail_NoStats', 'ALL'

我们再看下这个表的刚才查询,点击工具栏的显示包含实际的执行计划:

1 SELECT ProductID,COUNT(*) FROM dbo.SalesOrderDetail_NoStats GROUP BY ProductID

在没有任何统计索引和统计信息的情况下,优化器再一次在流聚合运算符的输出里估计行数是266。我们再次检查下这个表的统计信息。

1 EXEC SP_HELPSTATS 'SalesOrderDetail_NoStats', 'ALL'

是的,在估计执行计划是,SQL Server在productID 列创建了统计信息来帮助优化器选择正确的执行计划。我们来看看这个统计信息的详情。

1 DBCC SHOW_STATISTICS('dbo.SalesOrderDetail_NoStats', '_WA_Sys_00000005_7E6CC920') 

在统计信息头,我们注意到Rows Sampled 值比Rows值小。这是因为在自动创建统计信息时,SQL Server没有扫描整个表,只扫描了表的样本。为什么会这样在接下来的文章里会谈到。简而言之,在非聚集索引字段里,统计信息帮助优化器在每一步操作时判断估计行数,什么样的连接是合适的,还有在计划中的执行顺序。 



本文转自Woodytu博客园博客,原文链接:http://www.cnblogs.com/woodytu/p/4517401.html,如需转载请自行联系原作者
相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
关系型数据库 RDS
[物理学与PDEs]第1章习题15 媒介中电磁场的电磁动量密度向量与电磁动量流密度张量
对媒质中的电磁场, 推导其电磁动量密度向量及电磁动量流密度张量的表达式 (7. 47) 及 (7. 48). 解答: 由 $$\beex \bea \cfrac{\rd}{\rd t}\int_\Omega \cfrac{1}{c^2}{\bf S}\rd V &=\cfrac{\rd }{\rd...
916 0
|
6月前
|
Shell Android开发
Android系统 adb shell push/pull 禁止特定文件
Android系统 adb shell push/pull 禁止特定文件
511 1
|
6月前
|
Android开发 Python
Python封装ADB获取Android设备wifi地址的方法
Python封装ADB获取Android设备wifi地址的方法
144 0
|
开发工具 Android开发
Mac 安卓(Android) 配置adb路径
Mac 安卓(Android) 配置adb路径
788 0
|
3月前
|
Shell Linux 开发工具
"开发者的救星:揭秘如何用adb神器征服Android设备,开启高效调试之旅!"
【8月更文挑战第20天】Android Debug Bridge (adb) 是 Android 开发者必备工具,用于实现计算机与 Android 设备间通讯,执行调试及命令操作。adb 提供了丰富的命令行接口,覆盖从基础设备管理到复杂系统操作的需求。本文详细介绍 adb 的安装配置流程,并列举实用命令示例,包括设备连接管理、应用安装调试、文件系统访问等基础功能,以及端口转发、日志查看等高级技巧。此外,还提供了常见问题的故障排除指南,帮助开发者快速解决问题。掌握 adb 将极大提升 Android 开发效率,助力项目顺利推进。
69 0
|
6月前
|
Shell Android开发
ADB更改Android设备屏幕显示方向
ADB更改Android设备屏幕显示方向
318 5
|
6月前
|
Java Android开发
Android 对adb命令的拦截
Android 对adb命令的拦截
91 2
|
5月前
|
Shell 开发工具 Android开发