刚才有同事问我一个他觉得很奇怪的现象,一个表有30多G的数据,他使用一句简单的SQL语句查询表中的一行数据,执行计划显示数据库使用了聚集索引扫描,但执行时间只有0.3秒,为什么扫描30G的数据只需要0.3秒?
下面来看一下查询
set statistics io on
select * from EI_InterfaceContentLogs where TransId='EI_20140410133840630'
<p>(1 行受影响)
表 'EI_InterfaceContentLogs'。扫描计数 5,逻辑读取 54441 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。</p>
看IO统计来看,只做了54441次逻辑读取,大概只读取了400多M的数据,感觉是有点怪怪的,再看一下表结构:
注意到这里OutPut字段是nvarchar(max)类型,原因就和清楚了,nvarchar(max)数据默认是直接存储在数据行中(最大限制值为 8000 个字节,只要记录中可以容纳该值)。如果记录中容纳不下该值,则指针存储在行内,其余内容存储在 LOB 存储空间内,所以这里只需要扫描聚集索引的叶级页,找到对应的行后,再根据指针到LOB存储空间中去找到Output这一列的值。