最近论坛更换为DiscuzNT,在对数据库监测过程发现[dnt_getindexforumlist]这个存储过程的lob逻辑读取次数过大,且等待时间也相对较长。查看存储过程源码发现,其实这个存储过程很简单,也就是dbo.dnt_forums和dbo.dnt_forumfields两个表关联查询。主要原因出现在dbo.dnt_forumfields这个表上,该表共有text和ntext类型字段10个。我们知道text是做为LOB对象来存储的,在实际的存储中,数据记录页上存储的是该字段的一个指针,真正的数据是存储在LOB数据页上。因此查询每一条记录时,都需要10次的IO来读取该字段的实际值。

  解决方案很简单,只需要把text换为varchar(max),把ntext换为nvarchar(max)既可。为什么这样就能减少IO次数,提高性能呢?因为,varchar(max)类型的实际长度如果在8000字节以下,这个值将被做为普通的varchar类型来处理,只有在长度超赤8000时,才被做为LOB对象来存储。

  我们论坛的版块有290个,优化之后IO次数立马见分晓。

  优化之前的IO信息:

表 'dnt_forumfields'。扫描计数 1,逻辑读取 77 次,物理读取 0 次,预读 0 次,lob 逻辑读取 5801 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'dnt_forums'。扫描计数 2,逻辑读取 298 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

  优化之后的IO信息:

表 'dnt_forumfields'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'dnt_forums'。扫描计数 2,逻辑读取 298 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

posted on 2011-05-18 11:32  ideas  阅读(1099)  评论(2编辑  收藏  举报