优化你的DiscuzNT3.0,让它跑起来(1)看帖篇

注:本文仅针对 DiscuzNT3.0, sqlserver 2000版本,其他版本请勿对号入座. 

去年用DiscuzNT3.0做过二次开发,做过一些性能优化,但是时间关系一直没机会写下来;趁着5.1长假,来写篇回忆性的随笔吧。

 

之前看过园子里代震军同学的博客,知道了老代同学是DiscuzNT团队的一员,从他的博文学了不少东西 ,我这里写的博文是针对一些问题提出自己的看发和解决方案,针对问题并无针对任何人之意,秉着技术交流的原则。

 

DiscuzNT给我的印象是

1)功能很强大,所有你能想到的基本都已经有了;

2)性能有待优化,数据量较大的情况会产生性能瓶颈(这也正是写此文的目的)。之前发的博文由于缺乏经验,没有足够的论据,今天会多提供些图文并茂的论据。

 

好了,言归正转,开始我们今天的优化之旅。

 

本系统环境如下: 

软件环境:DiscuzNT3.0 , sqlserver2000,windwos server 2003

数据环境:主贴表 dnt_topics 约220万条记录,回复表3个,dnt_posts1 约400万, dnt_posts2 约500万, dnt_posts3 约500万,

    附件表 约170万,用户表 dnt_users 约20万, 论坛表 dnt_forums 约5000个论坛

现象:看帖时,如果帖子包含附件,会很卡;

目的:优化看帖速度,尤其是有附件的情况 

动手:看下它是如何获取附件的,找到showtopic.aspx.cs,代码如下:

postlist = Posts.GetPostList(postpramsInfo, out attachmentlist, ismoder == 1); 

 再看下 Posts.GetPostList() 方法的代码:

 1  ///   <summary>
 2           ///  获取指定条件的帖子DataSet
 3           ///   </summary>
 4           ///   <param name="_postpramsinfo"> 参数列表 </param>
 5           ///   <returns> 指定条件的帖子DataSet </returns>
 6           public   static  List < ShowtopicPagePostInfo >  GetPostList(PostpramsInfo postpramsInfo,  out  List < ShowtopicPageAttachmentInfo >  attachList,  bool  isModer)
 7          {
 8              List < ShowtopicPagePostInfo >  postList  =  Data.Posts.GetPostList(postpramsInfo);
 9               int  adCount  =  Advertisements.GetInPostAdCount( "" , postpramsInfo.Fid);
10 
11               foreach  (ShowtopicPagePostInfo postInfo  in  postList)
12              {
13                  LoadExtraPostInfo(postInfo, adCount);
14              }
15              attachList  =   new  List < ShowtopicPageAttachmentInfo > ();
16               if  (postList.Count  ==   0 )
17                   return  postList;
18 
19               string  pidList  =  GetPidListWithAttach(postList);
20              attachList  =  Attachments.GetAttachmentList(postpramsInfo, pidList);
21              ParsePostListExtraInfo(postpramsInfo, attachList, isModer, postList);
22               return postList;

23         } 

 

从这里可以看出,DiscuzNT是把所有的帖子id组装成 “ id1,id2,id3,id4 ” 的形式,然后传入数据库,避免多次调用数据库,这个思路很好,现在我们顺藤摸瓜,看看它调用了数据库的脚本,它调用了这个过程 dnt_getattachmentlistbypid, 用profiler跟踪这个过程看看性能。

 

 

 

看上面的图,exec dnt_getattachmentlistbypid @pidlist = '5163797'  这个脚本的cpu=4531,reads=152641,duration=6156,很可观吧,如果同时有10个人来调用这个过程,估计数据库的压力就大了,如果100人,难以想象。那我们怎么来优化这个过程呢,先看看里面它怎么写的,是否用到了索引。

 

ALTER     PROCEDURE   [ dnt_getattachmentlistbypid ]
@pidlist   varchar ( 500 )
AS
SELECT  
[ aid ] ,
[ uid ] ,
[ tid ] ,
[ pid ] ,
[ postdatetime ] ,
[ readperm ] ,
[ filename ] ,
[ description ] ,
[ filetype ] ,
[ filesize ] ,
[ attachment ] ,
[ downloads ] ,
[ attachprice ] ,
[ width ] ,
[ height ]  
FROM   [ dnt_attachments ]  
WHERE   CHARINDEX ( ' , ' + RTRIM ( [ dnt_attachments ] . [ pid ] ) + ' , ' ' , ' + @pidlist + ' , ' ) > 0

GO

 

这里主要查找的条件是pid,如果在pid列上建立索引,并且过程能用到索引,效果应该会更理想,这个优化工作我分为如下几步:

1)pid列上是否有索引;

2)过程是否用到了索引;

3)优化sql脚本; 

4)跟踪优化后效果;

 

我们一步一个坑往下走:

1)sp_helpindex dnt_attachments 看看是否有索引,如下图,从图中可以看到pid列上是有索引的,如果没有索引,请建立相关索引

 

 

2)看看是否用到了索引,CTRL + L 看看下面语句的执行计划,他用到的索引是 PK_dnt_attachments,根本没用到我们期望的pid

 

 

 3)没用到我们期望的索引,那我们就来优化一下;上面的dnt_getattachmentlistbypid过程里面 WHERE CHARINDEX(','+RTRIM([dnt_attachments].[pid])+',', ','+@pidlist+',')>0 对pid进行了列运算,这个是罪魁祸首,我们想办法把这个列运算去掉,这个过程最终改成下面这个样子:

ALTER      PROCEDURE   [ dnt_getattachmentlistbypid ]
@pidlist   varchar ( 500 )
AS

declare   @sql   nvarchar ( 2000 )

set   @sql   =   '
SELECT 
[aid],
[uid],
[tid],
[pid],
[postdatetime],
[readperm],
[filename],
[description],
[filetype],
[filesize],
[attachment],
[downloads],
[attachprice],
[width],
[height] 
FROM [dnt_attachments] 
WHERE pid in (
'   +   @pidlist   +   ' ) '

exec ( @sql)

GO

 

4)改完之后我们来跟踪下优化后的性能,看看跟踪效果图(同一个过程,同一个参数,第2个是优化前,第4个是优化后,优化效果灰常满意)

 

 

至此,我们的优化告一段落。

 

 

转载于:https://www.cnblogs.com/gezifeiyang/archive/2011/05/02/2034124.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值