http://www.cnblogs.com/zping/archive/2008/07/22/1249038.html
在上次做分页分析是分析时,执行下面语句:
FROM
[ dbo ] . [ [[zping.com ] ]]]]
WHERE
(ID NOT IN ( SELECT TOP ( 10 * ( 10000 - 1 )) ID FROM [ dbo ] . [ [[zping.com ] ]]]] ORDER BY ID DESC ))
ORDER BY
ID DESC
显示结果为:
这里有一点我有点疑惑:扫描计数 2
不光这里有 “扫描计数 2”,有时发现有其他sql语句时,就会对一个表扫描多次的统计信息
为何要扫描多次,什么情况下有多次扫描!
执行一下下面的语句:
where id = ' 402882ed0ea1c940010ea23329920093 '
or id = ' 402882ed0ea1c940010ea24ed9c400e8 '
or id = ' 402882ed0ea1c940010ea24edace00fc '
统计信息:
表 ' [[zping.com]] ' 。扫描计数 3 ,逻辑读取 12 次,物理读取 3 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
这时我们发现是 “扫描计数 3”
执行计划如图:
这里执行计划很简单:
先通过索引查找,找到索引的叶级数据索引健值,同时也找到中对应行的RID指针,通过嵌套循环找到对应行的全部数据。
注意:sql server会把对应行的RID和索引健值保存在索引叶级数据页(堆表)。
sql server会把表聚集索引(非唯一系统会加上一个4字节的唯一数据保证其唯一)和索引健值保存在一起索引叶级数据页中(聚集表)。
执行计划里就是一个从索引取取数据的描述。
我们再来看看下面语句:
inner join ( select ' 402882ed0ea1c940010ea23329920093 ' id
union
select ' 402882ed0ea1c940010ea24ed9c400e8 ' id
union
select ' 402882ed0ea1c940010ea24edace00fc ' id
) b on a.id = b.id
执行统计信息:
表 ' [[zping.com]] ' 。扫描计数 0 ,逻辑读取 12 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
这里的“扫描计数 0”
为何为”0“啊,结果都一样,就是实现方法不一样,“扫描计数 ”怎么有这样的差别。
上一次我们分析了两种写法不一样,产生的扫描计数差别很大,一个为3,一个为0,我们先看看后面的sql语句执行计划:
执行计划解释:
1,这里有两个合并排序,就是对3个id数据排序,通过合并算法排序(这里为何要用合并排序算法,我们在另一节中讨论)
2,通过排序后的数据,一次使用嵌套循环取出对应的索引值,一共循环三次。(嵌套循环算法将在另一节中讨论)
3,通过循环找到索引键值后,数据库也就找到了对应的行RID,这时通过嵌套循环找到行数据。
我们发现这时,索引和行数据查找是分开的。,也就是说找到索引和找到数据是分开的。这时扫描计数为0
我们还可以使用索引覆盖查找和表扫描,也都有扫描计数
通过上面的例子,总接一下:
扫描计数:数据库连续完整的找到一部分数据的次数。
以上是个人观点,如有错误请批评指正,一起学习进步!!!