存档

2010年2月25日 的存档,文章数:3

CSDN上有篇帖子http://topic.csdn.net/u/20100223/15/644e6212-9fdc-42de-81ad-785d28ed71d3.html 讨论查询计划读取索引页的问题。 主要问题是: 在一张建有聚集索引(没有其它非聚集索引)的表执行select count(*) 。查询显示扫描了所有的索引中间层叶。从理论上讲,由于每个数据页都记录着它的上一个page和下一个page,那么最小的io读取应该是: 读根页—>读最小的中间页—>读数据叶子—->依次往后读全部数据页. 但实际上却是读取全部的索引中间页。 帖子中比较精彩的回复: 1 2 3 4 5 首先楼主的说法不够准确,根据我的测试结果来看,更准确的说法应该是sql server在做索引全扫(INDEX FULL scan)时,会先扫描全部的level 1的节点,然后在扫描处于level 0的叶节点。也就是说一次索引全扫的顺序是(这个顺序对于clustered INDEX和普通INDEX都是一样的): 读根页—>读最小的中间页(level 1以上的层)—>依次读level 1的所有节点的索引页—->读全部数据页 上述顺序可以在将数据表索引层数增加到3层以上时得到验证。 实际上我觉得sql server这样做是很有道理的,楼主认为的是所读的页越少,io就越小,这是不对的。对于sql server来说,一次io并不一定只读取一个页,很多时候特别是做表全扫或索引全扫时,sql server都会尽量的让一次io读取尽可能多的数据页,这样才能较少io的次数。为达到这个目的,sql server首先就要知道它到底需要读取那些页,知道要读取页的分布之后,就可以安排io调度器尽可能的将临近的数据页用一次io读取上来,而要知道需要读取数据页的分布就需要先读取到level 1上的所有页,以找出要读取io页的分布情况,然后再做最优的io读取安排。 同样的道理,如果sql server是先定位到叶节点的起始数据页,然后从依次的读取所有的数据页的话,那sql server就只能一次io读取一个数据页,然后找出对应的下一页的指针,再去读取下一个数据页,这样实际上花费的io会远比批量读取数据页多很多的。这就好比我们在做表的lookup时,如果需要lookup的行非常之多的话sql server会转而选择表扫描来达到目的的。 预读 我觉得SQL Server内部存在这样一个机制: 它会尽量将当前使用的及使用最频繁的表的数据都带到buffer中来,这跟buffer的算法有一定的关系。 清掉buffer後,你不做任何动作,隔几秒钟,sql会自动将master库中一些比较重要的表都带到buffer中,或者 你select * from tb where 1 <>1 ,尽管该查询不会扫描任何数据,但sql还是会自动将tb的所有索引页到带到 buffer中去,因为它可能觉得tb这个表後续可能会使用到. 关于计算逻辑读的数量 IAM页是否会计算在逻辑读中我都是持怀疑态度的。 比如说,一个堆表扫描时肯定是从IAM页开始的,然而用set statistics io on看到的逻辑读数量却只是表所占用的总页数,并没有加上相应的IAM页数量。 [...]

– 创建测试数据库 CREATE DATABASE Db GO — 对数据库进行备份 BACKUP DATABASE Db TO DISK = ‘ c:\db.bak ‘ WITH FORMAT GO — 创建测试表 CREATE TABLE Db.dbo.TB_test(ID int ) — 延时1秒钟,再进行后面的操作(这是由于SQL Server的时间精度最大为百分之三秒,不延时的话,可能会导致还原到时间点的操作失败) WAITFOR DELAY ‘ 00:00:01 ‘ GO — 假设我们现在误操作删除了 Db.dbo.TB_test 这个表 DROP TABLE Db.dbo.TB_test — 保存删除表的时间 SELECT dt = GETDATE () INTO # GO — 在删除操作后,发现不应该删除表 [...]

在sybase表上建立聚集索引可以提高键列的检索速度。这是索引的主要功能所在。 可是,聚集索引对于统计表上的行数count(*)有没有改善呢? 答案是否定的。 请看我下面的测试代码! 建立一张临时表test3 1 create table test3(id int not null,name varchar(30) null) 向表中插入测试数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 insert into test3 select 1,’liu’ go insert into test3 select 2,’zhang’ go insert into test3 select 3,’wang’ go insert into test3 select 4,’li’ go 循环插入 [...]