SQL Server索引进阶之页和区

发表于:2012-9-12 10:20

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:CareySon 译    来源:51Testing软件测试网采编

分享:

  每行的字节数包含所有列的字节数相加外加行开销,有很多因素决定行开销的大小,这些因素可以总结如下:

  ● 每行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列。

22/2<12
价值398元的测试课程免费赠送,填问卷领取吧!

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计

法律顾问:上海漕溪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2023
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号