SQL Server在堆表中查询数据时,是不知道到底有多少数据行符合你所指定的查找条件,它将根据指定的查询条件把数据表的全部数据都查找 一遍。如果有可采用的索引,SQL Server只需要在索引层级查找每个索引分页的数据,再抓出所需要的少量数据分页即可。访问数据表内数以万计的数据 分页与只访问少数索引的分页两者间的差异,让索引变成效能调校的最佳工具。

堆表的结果示意图:
堆表内的数据页和行没有任何特定的顺序,也不链接在一起。数据页之间唯一的逻辑连接是记录在 IAM 页内的信息。
假设订单明细表中有100万条数据,需要查询某个订单的明细数据,如下:
select* from T_EPZ_INOUT_ENTRY_DETAIL where entry_apply_id='31227000034000090169'
如果在堆表中进行查询,SQL Server通过扫描 IAM 页对堆表进行全表扫描,对entry_apply_id比较100万次,如果以 entry_apply_id字段建立索引,则因为索引键值数据都必定以B-Tree有顺序的摆放,所以可采用二分查找找数据。也就是2的N次方大于记录 数,就可以找到该条数据。而2的20次方大于100万,因此最多找寻20次就可以找到该条记录。20次与100万次的比较,你可以轻松感受出性能的差异。
下面我们举个实例来做说明:
一、表空间的高度碎片化
1.此表的碎分布信息,从下图中可以看出此表的有非常多的内部碎片与外部碎片。
a) 此表的平均页密度只有24%,也就是说平均一页只有1/4空间才有数据,其他的3/4空间都是空着,有着很多的内部碎片。
 
b) 此表的扫描密度只有13%,也就是说理论上的区的数量与实现上区的数量之比为1:7.5,也就是说存在非常多的外部碎片,也就是说每个区的利用率相当低,一个区的数据全部加起来,才一个数据页。
如下图。

对字段的说明:(例二、例三中的图中字段说明是一样的。)
Pages:如果在DBCC SHOWCONTIG 语句中指定了index_id,则将遍历指定索引的叶级上的页链,索引为叶子层使用的分页数目。如果只指定 table_id,或者 index_id 为 0,则将扫描指定表的数据页。
AvgeragePageDensity:平均页密度(为百分比)。该值考虑行大小,所以它是页的填满程度的更准确表示。百分比越大越好。 
ScanDensity:扫描密度(为百分比)。这是“BestCount”与“ActualCount”的比率。如果所有内容都是连续的,则该值为 100;如果该值小于 100,则存在一些碎片。
2. SQL查询语句与查询执行计划成本
--查询语句:
SET STATISTICS IO on
go
SET STATISTICS TIME on
go
select  * from T_EPZ_INOUT_ENTRY_DETAIL where entry_apply_id='31227000034000090169'
go
SET STATISTICS IO off
go
SET STATISTICS TIME off
go

3.查询所需要的时间与I/O
SQL Server 执行时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 16 毫秒,耗费时间 = 76 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
(所影响的行数为 13 行)
表 'T_EPZ_INOUT_ENTRY_DETAIL'。扫描计数 1,逻辑读 4825 次,物理读 6 次,预读 19672 次。
SQL Server 执行时间: 
CPU 时间 = 47 毫秒,耗费时间 = 10544 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 执行时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
二、表低度碎片化
1. 此表的碎分布信息,从下图中可以看出此表的有非常多的内部碎片与外部碎片。
a) 此表的平均页密度只有97%,也就是说数据差不多把一个数据页都塞满了,没有多余的空间,没有内部碎片。
b) 此表的扫描密度只有98%,也就是说理论上的区的数量与实现上区的数量之比为1:1,也就是说基本上没有外部碎片,也就是说每个区的利用率相当高。
如下图。
备注:对于上图中的一些字段说明,见(一)。
2.SQL查询语句与查询执行计划成本
--查询语句:
SET STATISTICS IO on
go
SET STATISTICS TIME on
go
select  * from T_EPZ_INOUT_ENTRY_DETAIL where entry_apply_id='31227000034000090169'
go
SET STATISTICS IO off
go
SET STATISTICS TIME off
go


3.查询所需要的时间与I/O
SQL Server 执行时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 92 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
(所影响的行数为 13 行)
表 'T_EPZ_INOUT_ENTRY_DETAIL'。扫描计数 1,逻辑读 1205 次,物理读 0 次,预读 1209 次。
SQL Server 执行时间: 
CPU 时间 = 16 毫秒,耗费时间 = 390 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 执行时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
说明:逻辑读取的数值十分接近数据库中数据页数字,预读的次数也十分接近数据页的数字,物理读取值为0,即所需要查询的数据全部在预读的数据中间。
三、表添加主键,我们看一下有索引的查询
1. 此表的碎分布信息,从下图中可以看出此表的有非常多的内部碎片与外部碎片。
a) 此表的平均页密度只有97%,也就是说数据差不多把一个数据页都塞满了,没有多余的空间,没有内部碎片。
b) 此表的扫描密度只有98%,也就是说理论上的区的数量与实现上区的数量之比为1:1,也就是说基本上没有外部碎片,也就是说每个区的利用率相当高。
如下图:

备注:对于上图中的一些字段说明,见(一)。
2.SQL查询语句与查询执行计划成本
--查询语句:
SET STATISTICS IO on
go
SET STATISTICS TIME on
go
select  * from T_EPZ_INOUT_ENTRY_DETAIL where entry_apply_id='31227000034000090169'
go
SET STATISTICS IO off
go
SET STATISTICS TIME off
go

3.查询所需要的时间与I/O
SQL Server 执行时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 98 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
(所影响的行数为 13 行)
表 'T_EPZ_INOUT_ENTRY_DETAIL'。扫描计数 1,逻辑读 3 次,物理读 2 次,预读 0 次。
SQL Server 执行时间: 
CPU 时间 = 0 毫秒,耗费时间 = 30 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 执行时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 分析和编译时间: 
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
比较以上三者的各种关键值,就可以看出性能的提升程度。

物理操作
逻辑操作
I/O成本
CPU成本
成本
子树成本
逻辑读
物理读
预读
 
例一:堆表高度碎片化
Table Scan 逻辑运算符和物理运算符检索 Argument 列内指定表中的所有行
同左
3.61
0.0342
3.645123
3.65
4825
6
19672
例二:堆表低度碎片化
同上
同左
0.464
0.0171
0.963642
0.963
1205
0
1209
例三:表(带主键)
Clustered Index Seek 逻辑运算符和物理运算符利用索引的查找能力从聚集索引中检索行
同左
0.0032
0.000086
0.003289
0.00328
3
2
0
例一/例二/例三
1128/145/1
397/198/1
1108/292/1
1112/293/1
1608/401/1
3/0/1
16/1/0

对表中列的说明:
物理操作:使用的物理运算符,例如 Hash Join 或 Nested Loops。
逻辑操作:与物理运算符匹配的逻辑运算符,如 Join 运算符。
I/O 成本:用于操作的所有 I/O 活动的预计成本。该值应尽可能低。
CPU 成本:用于操作的所有 CPU 活动的预计成本。
 
成本:查询优化器执行此操作的成本,包括此操作的成本占查询总成本的百分比。由于查询引擎选择最高效的操作执行查询或执行语句,因此该值应尽可能低。
子树成本:查询优化器执行此操作及同一子树内位于此操作之前的所有操作的总成本。
在本文的三个例子中,预读值最高的为19672,最低的为0,物理读的值最高为6,最低为0,而逻辑读的值最高为4825,最低为3。
 
那么我在服务器上 执行查询时的过程是怎么样的呢?以例一为例。
首先,SQL Server会开始检查完成查询所需要的数据是否在数据缓冲区中,它会很快地发现这些数据不在数据缓冲区中, 并启动预读机制将 它所需要的数据页读取到数据缓冲区中,但是由于数据页碎片严重情况,需要多次切区,大大提升了I/O的消耗,如例一中读取19672次,所以当碎片非常严 重时,I/O读取非常频繁,多读取了4倍的数据页。
 

其次,如例一,当SQLServer检查是否所需要的全部数据都已经在数据缓冲区时,会发现已经有4819个数据页在数据缓冲区中,还有六个数 据页不在,它就会立即再次读取磁盘,所以有了6次的物理读,在将所需要的页读到数据缓冲区。一旦所有的数据都在数据缓冲区后,SQL Server就可以 处理查询了。

SQL Server查询性能优化——堆表、碎片与索引(一)相关推荐

  1. SQL Server 查询性能优化——堆表、碎片与索引(一)

    SQL Server在堆表中查询数据时,是不知道到底有多少数据行符合你所指定的查找条件,它将根据指定的查询条件把数据表的全部数据都查找一遍.如果有可采用的索引,SQL Server只需要在索引层级查找 ...

  2. Sql Server查询性能优化之走出索引的误区

    据了解绝大多数开发人员对于索引的理解都是一知半解,局限于大多数日常工作没有机会.也什么没有必要去关心.了解索引,实在哪天某个查询太慢了找到查询条件建个索引就ok,哪天又有个查询慢了,再建立个索引就是, ...

  3. Sql Server查询性能优化之索引篇【推荐】

    Sql Server查询性能优化之索引篇[推荐] 这篇是索引系列中比较完整的,经过整理而来的 一 索引基础知识 索引概述 1.概念 可以把索引理解为一种特殊的目录.就好比<新华字典>为了加 ...

  4. SQL Server 查询性能优化——覆盖索引(二)

    在SQL Server 查询性能优化--覆盖索引(一)  中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索 ...

  5. SQL Server 查询性能优化——创建索引原则(一)

    索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索引 ...

  6. SQL Server Insert 操作效率(堆表 VS 聚集索引表)

    "SQL Server的Insert操作在堆表或者聚集索引表的时候,哪个效率更高?为什么高?" 之前有同事问过我这个问题,为了确保日志库的记录效率,于是我做了简单测试了,首先要先强 ...

  7. SQL Server 查询性能优化——覆盖索引(一)

    覆盖索引又可以称为索引覆盖. 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖. 解释二: 索引是高效找到行的一个方法,当能通过检索索引 ...

  8. SQL Server 2005 性能优化实战系列(文章索引)

    http://www.cnblogs.com/gaizai/archive/2012/01/20/2327814.html 前言 性能优化是数据库方向一个很重要的技能,这也是快速提供企业级应用性能最快 ...

  9. 【SQL Server】性能优化-索引

    性能优化-索引 1 索引 1.1 什么是索引 1.2 索引的存储机制 1.3 创建索引原则 1.4 如何创建索引 1.4.1 创建索引 1.4.1 删除索引 1.4.1 显示索引 1.5 索引使用次数 ...

最新文章

  1. python open方法下file模块_python-linecache模块读取文件用法
  2. yaf_dispatcher.c 的 yaf_dispatcher_fix_default函数
  3. mysql-5.2 lib_Centos 5.2下安装多个mysql数据库配置详解
  4. Angular中使用HttpClientModule模块实现get请求数据和post提交数据
  5. C++中全局函数和局部函数的关系
  6. 加油四班!加油佟穆!我们的征途是星辰大海!!!
  7. sqlrelay mysql_php+sqlrelay+mysql实现连接池及读写负载均衡
  8. arduino joy_如何用Joy开发Kubernetes应用
  9. 为啥学java要看那么多东西_编程语言那么多,为啥学Java的人那么多?
  10. mongodb统计函数
  11. 《Windows Phone 7 用户界面设计和交互指南 v2.0》
  12. Python练习-装饰器版-为什么我的用户总被锁定
  13. 【深入理解JS核心技术】1.在 JavaScript 中创建对象的可能方式有哪些?
  14. python怎么写入聚类标签_标签传播算法(Label Propagation)及Python实现
  15. tp无线路由器设置打印服务器,打印服务器复位大全tplink路由器设置
  16. 《甄嬛传》计谋汇总, 本文忠实于《后宫 甄嬛传》第1本~第7本+番外原文,而非电视剧。
  17. RNN/LSTM (四) 实践案例改编
  18. Transformer 中 Decoder 结构解读_by 弘毅
  19. JSP编译指令-page
  20. L84.linux命令每日一练 -- 第11章 Linux系统管理命令 -- rpm和yum

热门文章

  1. Android-- FragmentStatePagerAdapter分页
  2. jQuery实现id模糊查询
  3. VS2005 实用快捷键,迅速提高代码编写效率!
  4. 非常有创意的音乐网站
  5. shell mysql e_xshell怎么搭建mysql
  6. SQLite的sqlite_master表
  7. Xamarin.Forms的基本页面和基本视图
  8. Swift3.0语言教程使用Unicode范式标准化获取字符串
  9. 【分享送书】NGUI全面实践教程V3.8.2 活动开始了!!
  10. 计算机组成原理第3版谢树煜,计算机组成原理(第3版)