现在的位置: 首页 > 综合 > 正文

关于逻辑读

2018年04月09日 ⁄ 综合 ⁄ 共 1240字 ⁄ 字号 评论关闭

 问:

 

      我用的是SQL2005自带的AdventureWorks数据库,在执行如下语句时:
SQL codeselect*fromSales.SalesOrderHeaderwherecustomerid='676'
查看执行计划:
SQL codeTable'SalesOrderHeader'. Scancount1, logical reads38, physical reads0,read-ahead reads0, lob logical reads0, lob physical reads0, lobread-ahead reads0.
按照我的理解,其中逻辑读38应该是从数据缓冲区读区的页数,可上述SQL语句只返回12行记录,怎么会有38个数据…

答:

一、

-------------------------------

我通过sys.dm_db_index_physical_stats函数获取该表索引的数据页层次结构

SELECT * FROM
sys.dm_db_index_physical_stats(DB_ID(N'AdventureWorks'), OBJECT_ID(N'Sales.SalesOrderHeader'), NULL, NULL , 'DETAILED');

发现聚集索引有3层  建立在customerid字段上的非聚集索引有2层

所以数据查询  是这样的步骤 :
1、在非聚集索引查找  两个数据页  获得所有非聚集索引子叶(指向聚集索引)的
2、每行数据都要通过聚集索引查找数据 12*3=36

最后逻辑读=36+2

 

二、

-----------------------------
逻辑读38页 = customerid 所在的非聚集索引页 + 12行记录所在的聚集索引叶.
所以这个值大于>12是很正常的.

其过程解释:

--1.通过CustomerID所在的非聚集索引读出SalesOrderID,这个只需读2个页面
select CustomerID,SalesOrderID from Sales.SalesOrderHeader where CustomerID='676'
/*
(12 行受影响)
表 'SalesOrderHeader'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
*/
--2.然后根据上面的结果,从Sales.SalesOrderHeader根据聚集索引,查找所有列,这个扫了36个page
select * from Sales.SalesOrderHeader
where SalesOrderID in
(43659,44305,45061,45779,46604,47693,48730,49822,51081,55234,61173,67260)
/*
(12 行受影响)
表 'SalesOrderHeader'。扫描计数 12,逻辑读取 36 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
*/
--3.共扫描了38个页面

 

抱歉!评论已关闭.