SQL Server索引进阶第四篇:页和区
作者:网络转载 发布时间:[ 2012/9/12 10:28:16 ] 推荐标签:
每行的字节数包含所有列的字节数相加外加行开销,有很多因素决定行开销的大小,这些因素可以总结如下:
● 每行6字节用于存储状态信息和长度信息
● 每列占一位,向上取整到字节
● 如果包含变长数据,第一个变长列4个字节,之后每个变长列额外占两个字节
● 除此之外,页尾还包含每个行2个字节的偏移指针
因为SalesOrderDetail含有变长列,所以每行所占的大小并不能提前预测,但是还是可以算出平均每行所占的字节为95字节。因为每页的大小是8k,因此每页大约可以容纳75行,这要比我们上面的例子多出很多,在接下来的文章中我们将会详细讨论通过SQL Server management studio来查看每页所含的行数。
所以,虽然我们通常说SQL Server是”读取行”,但如果深究起来这种说法是错误的,其所读取的小单位是页。我之前的也说过SQL Server通过给定的索引键值可以快速的找到行,但其实深究的话正确的说法是SQL Server通过给定的索引键值找到页。在SQL Server将找到的页存入内存之后,在从内存中找到指定的行。
区
SQL Server基于页之上做了另外一种逻辑分组,它将8个物理上连续的页分为一个区。正常情况下,和页一样,区也是所有权的小单位,如果区中的一页属于表A或者表B,那么区中其它页也属于表A或者表B,但对于特别小的表或者索引不适用了,对于很小的表和索引,一个区中的页可以属于两个以上的表。但对于大多数区来说,区都是所有权的基本单位。
因此,对于表扫描来说,SQL Server并不是扫描所有的行,而是属于表的所有的页和区。SQL Server对于IO做的请求是8K或者64K字节的请求,甚至可能是并行读取表。这使得表扫描并不像想象的那么吓人,因为扫描是页为单位而不是每行都要做一个IO请求。
以页和区作为单位不仅仅意味着减轻了表扫描的成本,还意味着,要从非聚集索引获益,查询请求的过滤条件要更具有选择性。加下下面的对于SalesOrderDetail表的请求,获取这个表4%左右的数据。
查询
SELECT *
FROM Sales.SalesOrderDetail
WHERE ProductID = 712
聚集索引
SalesOrderID / SalesOrderDetailID
每页平均行数
75
非聚集索引
ProductID
请求行所占比例
4%
因为平均每25行中只选择一行,并且where后的条件是根据ProductID来的,而且还存在以ProductID作为KEY的非聚集索引,索引使用非聚集索引来定位每行的信息看上去是个不错的主意,是这样吗?请在想一想。
由于表中以SalesOrderID/SalesOrderDetailID作为聚集索引,因为平均每页存在75行数据,而查询从每25行中取一行,也是平均每页只能取三行。换句话说,几乎表中的每一页都要读到内存中才能满足这个查询,因此还不如直接进行聚集索引扫描来的快,因为扫描以区为单位,因此每次IO请求可以将24行数据载入内存(3行每页*8页每区)。
SQL Server新手通常会问”非聚集索引在什么样的选择率下才会被使用”,在本篇文章中你可以知道,比平均每页只能获取查询请求的一行要多行。本系列文章接下来的章节中将会包含更多细节。
总结
SQL Server读取的单位是页而不是行。页是IO小的单位,也是8K,8个连续的页被称为区。通常情况下,页和区都只能属于一个对象,因为IO读取的特性,一个查询必须要有很高的选择率才能够从非聚集索引获益。
在第五篇文章中,我们来看如何提高使用非聚集索引来减少查询成本的概率。一种解决方法是非聚集索引完全覆盖所请求的查询。换句话说,下一讲我们讲解使用Include列。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11