dedecms

关注公众号 jb51net

关闭
首页 > 网站技巧 > 整站程序 > dedecms > dedecms 性能优化

dedecms负载性能优化实例,三招让你的dedecms快10倍以上

投稿:mdxy-dxy

对dedecms表现出来的相对较差的性能也感觉比较迷惑,到底是什么在制约其负载效率?难道真的是某些脑残的dede论坛版主说的是因为mysql不堪重负的原因吗?

还是因为一个表的大数据造成性能严重下降?难道我们必须通过分多个表来存储才能解决问题吗?以下我们通过一个实例来解析和优化dedecms的数据管理性能,千万别让mysql当替罪羊,罪莫大焉。
测试数据是无意中得到的企业黄页的数据,数据量将近90万,都是完全真实的数据,测试使用的程序是dedecms4.0版本,你问为什么不用dedecms5.1?那是因为我们为了优化,针对dedecms做了很多修改,如果使用dedecms5.1,我们害怕收到法院传票……,补充一句,以下的优化方法均能在dedecms5.1中使用,请在理解其原理的基础上自行完成。

未优化前我们测试发现主要有三个经常性的操作在dede大数据量的情况下影响管理性能,分别是文档生成、列表页生成和栏目列出所有文章,我们就针对这三个方面进行优化实践。
以下是测试数据的基本信息:

optimize-dede1.jpg

文档数量接近90万

每个栏目包含近3万数据

1.改进文档生成速度

问题提出

        和我们前一次测评结果相同,dedecms的文档的生成速度惨不忍睹。使用默认模板(article_article.htm),平均接近30秒才能生成20个页面(如图),按照这个速度生成下去,90万的数据全部生成网页能等到头发都白了。那么到底问题在哪里呢?

optimize-dede3.jpg

优化前单个栏目文档生成速度

问题分析

        先排除表索引的问题,因为dede的数据库已经在数据主表(dede_archives)为主要字段都建立了索引。再排除主要内容的提取效率问题,因为页面生成过程中读取页面中的文章数据,每次需要到主表和附表中select取得id值唯一的数据内容,这个SQL语句的效率我们通过直接在mysql中运行SQL语句测试,执行时间非常短,因此这也不是最大的瓶颈。

        终于在页面生成过程中,我们发现程序执行了数次主表(dede_archives)查询,并取出符合一组复杂查询条件数据的操作,查询效率非常低,原来是它在影响效率!通过调试跟踪,我们定位了问题的关键,元凶就是模板中arclist标签。Arclist标签是很多人很喜欢用的标签,因为它比较灵活,能从数据中取出热门、最新、相关等各种类型的文章列表,但是arclist标签每次都会带着一大推搜索条件去主表中查询,实际上对于一次性生成大量文章来说,如果使用相同的模板,arclist对数据库的查询操作只是简单机械重复罢了,为此而耗费了大量时间绝对是不值得的。接下来我们给出问题解决的建议。

解决问题

解决方案1:去掉最终页面模板中的arclist标签,或者尽可能少用。这个方法虽然能极大提高效率,但是无异于泼水把孩子泼走了,对于企图增加访问pv的网站来说,不建议使用。

解决方案2:建立arclist缓存,将每次arclist生成的数据放到临时目录或者缓存当中,在文档生成过程中判断缓存是否有更新,如果无更新,直接使用缓存数据。这个方法无需改变模板,对于提高生成效率也有一定的效果,但由于对程序改动较大,酌情考虑使用。

解决方案3:也是小组建议的解决方案,那就是充分挖掘现有dedecms的功能,在尽量不改变程序的基础上,大幅提高效率。具体的方法就是通过freelist(自由列表生成)功能事先生成热门文章、最新文章、相关文章等内容的列表页面,然后使用dedecms提供的include标签直接引入文档页面。标签格式为:{dede:include file='列表页面文件名称' ismake=' no'/}。这个方案优点在于仅增加部分操作步骤,没有改动任何程序,性能提高亦非常明显。下图就是我们利用这个方法优化后的生成速度,仅用时50秒就完成了1500多页的文章生成,达成目标优化效果。此方案由于增加了操作步骤,懒人慎用。

optimize-dede4.jpg

优化后单个栏目文档生成速度

2.改进列表页面生成速度

问题提出

        接下来我们继续测试列表页面的生成,这次我们学乖了,先把模板(list_article.htm)中的arclist标签删除后再测试,但是生成效果依然非常不理想。如下图,每个列表页面生成时间接近20秒(我们修改了页面结果输出提示,为了大家更方便看到每个列表页面生成时间),按照每页50条数据计算,生成单个栏目的3万数据理论上也要花费3个多小时,生成90万数据……无语ing。由于列表内容使用的是list标签,这是一个和arclist有点类似的标签,因此我们不能延续上面的做法来解决问题,只能另辟蹊径。

优化前的列表页面生成速度

问题分析

        由于目标锁定在list标签,测试的过程就简单了。我们直接使用dedecms中list的查询语句做优化分析,很快发现了问题。我们测试了list中的sql查询语句,以下代码就是list用来查询数据库中对应条件的SQL语句,执行时间大约为15秒,效率很不理想。

Select arc.ID,arc.title,arc.iscommend,arc.color, arc.typeid,arc.ismake,arc.money,arc.description,arc.shorttitle, arc.memberid,arc.writer,arc.postnum,arc.lastpost, arc.pubdate,arc.senddate,arc.arcrank,arc.click,arc.litpic, tp.typedir,tp.typename,tp.isdefault,tp.defaultname, tp.namerule,tp.namerule2,tp.ispart,tp.moresite,tp.siteurl from dede_archives arc left join dede_arctype tp on arc.typeid=tp.ID left join qiye_addonarticle on arc.ID = qiye_addonarticle.aid where arc.arcrank > -1 And ( ( arc.typeid='1′ ) or arc.typeid2='1′) order by arc.sortrank desc limit 0,50

        我们注意到这个SQL语句中的where子句使用了and和or的多种条件判断,经验告诉我们如果查询子句中使用了in或者or语句,会导致全表扫描,这样的话索引的效率就无法体现。我们简化了where子句的判断条件进行测试,结果发现删除了or子句之后,查询效率大幅提升,上面的查询语句只用时不到1秒就获得了查询结果。这就是问题关键。

解决问题

        对于list查询来说,arc.typeid2='1′这个条件目的是查找某个文章所属的第二分类,而事实上这个功能在大部分情况下很少使用,因为我们大可使用标签(tag)来完成一篇文章的多个不同分类的归属,因此我们修改文件inc_arclist_view.php,在查询语句中直接删除了typeid2的条件判断,并在pub_db_mysql.php中改进了查询执行函数(主要用于提高sql语句执行的效率,对最终结果影响不大),得到的最终测试结果如下,平均每个列表页面的生成时间下讲到不到1秒,3万数据600个列表页面生成只需要花费不到10分钟,优化目标达成。

优化后的列表页面生成速度

3.改进文档管理效率

问题提出

        在90万这个数据量的情况下,dedecms打开栏目文章列表,尤其是打开所有档案列表企图进行文章管理的时候,速度简直无法让人忍受。我们点击所有文档列表,耐着性子等了将近2分钟,文章列表页面才姗姗来迟。到底什么在制约着文章列表速度呢?

优化前使用所有档案列表数据加载完成时间

分析问题

        控制显示文档列表的程序是dede/content_list.php和include/pub_datalist_dm.php,其中content_list.php是主控制程序,完成列表的参数传递和模板显示,而pub_datalist_dm.php用于完成数据查询和分页等操作。通过程序调试,我们找到了问题的结症在于pub_datalist_dm.php程序中对于全部数据的统计花费了大量的时间,而使用limit的列表数据的查询并不是性能的瓶颈。影响效率的关键代码为:

$this->dsql->Query();
$this->totalResult = $this->dsql->GetTotalRow();

        这里所用的数据总数统计的方式居然是通过content_list.php传递过来一个复杂的查询语句,然后执行这个查询并将结果保存到数据集中,最后通过mysql_num_rows函数统计结果集中行的数目,完全没有想到dedecms居然走了一个最远的路途完成一个最简单的操作,难怪效率低得可怕。因此只要我们改用最常见的count方法来统计数据,执行效率就能大幅提高。

解决问题

        首先我们修改了程序content_list.php,构造了$conutquery参数用来保存统计使用的SQL语句,代码如下:

……
$conutquery=”
select count(*) as totalResult
from #@__archives
left join #@__arctype on #@__arctype.ID=#@__archives.typeid
left join #@__channeltype on #@__channeltype.ID=#@__archives.channel
left join #@__admin on #@__admin.ID=#@__archives.adminID
$whereSql
order by #@__archives.{$orderby} desc”;
……

        然后将这个参数和查询$query参数一起传递给pub_datalist_dm.php进行处理。

$dlist->SetSource($query,$conutquery);

        随后将pub_datalist_dm.php中获得数据总数统计的代码替换为使用$conutquery参数:

……
//统计优化
$row = $this->dsql->GetOneSimple($this->countSql);
$this->totalResult = $row['totalResult'];
……

        其中GetOneSimple是新构造的一个用来执行SQL语句的函数,我把它放在了pub_db_mysql.php类里面,主要的用途就是返回SQL语句执行结果, $this->countSql是上一个程序传递过来的统计使用的SQL代码,$this->totalResult用来记录数据统计结果。程序修改之后,获得了满意的效果。

优化后使用所有档案列表数据加载完成时间

总结

        通过对以上几步优化操作,现在我们的程序后台已经能够非常轻松的应付90万数据的管理和维护了,事实证明dedecms的负载性能的瓶颈并不是mysql、服务器或者操作系统平台等,如果把未经优化的程序放到oracle的数据库上,使用更高级别的服务器,使用freebsd的操作系统,表现一样会不尽如人意。细节决定成败,看起来dedecms必须要在程序调优、性能优化上好好下功夫了。想了解更详细的解决方案,请加入我们交流。

下面是其他网友的补充

前文介绍了DedeCMS栏目列表页实现完美分页的方法,避免了大部分重复栏目标题对搜索引擎的影响,对SEO更有利。今天,分享一下DedeCMS数据负载性能优化的方法。

接触织梦也有三年多时间了,对它可谓是又爱又恨。它的模板简单易用,标签调用更是灵活,二次开发也非常方便。可是,站点数据庞大起来的时候(30多 万条),后台就会变得异常缓慢,生成HTML也很吃力,毫不夸张的说,头发都等白了。这不禁让我对DedeCMS数据负载性能产生了置疑?

查阅了相关资料,结合自身站点实际,还是总结出了一套不错的DedeCMS数据负载性能优化方案。废话不说,直接进入正题。

1)数据分表存储 减轻数据单表压力

自织梦V5版本起,DedeCMS开始分表存储以提高系统负载性能,确实在一定程度上缓解了数据压力。现在最新的DedeCMS V5.7版本已经出来了,据官方介绍,V5.7调整了缓存处理,应付50万以内数据没问题,至于真实性无从考究。如果官方陈述属实的话,对于中小型站长来 说确实是件好事,正常百万级内数据也不用过多担心了。

分表存储如何操作?

如果你只是个人或企业等小型站点,数据量也就撑死上万,那完全不用考虑分表存储,DedeCMS完全可以胜任。分表操作很简单,你只需要直接进入后 台,新建模型,然后设置一个栏目对应一个模型。个人建议一个大的频道栏目及子栏目对应一个模型,这要根据你的栏目可能存储的数据来做计划,考虑实际一点的 分表方案。

2)修改系统参数 arclist标签另类优化

在DedeCMS V5版本中,官方其实已经做了极力优化,引入了缓存机制。其实影响HTML生成速度的罪魁祸首还是模板中的arclist标签,很多站长喜欢用 arclist标签来调用最新、热门、推荐、头条等文章列表,但是arclist标签每次都带着一大堆条件去主表中查询,可能还会关联附加表,对一次性生 成大量文章来说,只是重复使用arclist标签对数据库重复查询罢了,自然会花去大量时间。现在DedeCMS新的版本中,生成HTML时arclist标签会直接调用缓存数据,省去arclist标签重复查询数据库的时间,顿时让上述工作变得轻松起来,生成速度得到提升也是必然的。你只用在系统参数->性能选项中,找到arclist标签调用缓存(cfg_index_cache)(0 不启用,大于0值为多少秒),根据自身实际需求调整缓存调用时间。

其实,还有一种解决办法,就是麻烦了一些,但是对性能提升是非常显著的。arclist 标签调用缓存虽说一定程度上提高了HTML生成速度,但是还是需要对arclist缓存进行判断,如果能把这部分时间也省去,那是不是会更快呢?答案是肯 定确定以及双重否定。我们可以通过freelist(自由列表)功能事先生成最新、热门、推荐、头条等文章列表页面,然后用include标签直接引入到 模板里,标签格式为:{dede:include file='文章列表页面文件名称' ismake=' no'/}。如果你的站长数据很庞大,服务器硬件配置也一般的话,何不尝试一下呢?

另外,系统参数-核心设置里默认的关键字替换功能(cfg_keyword_replace)是开启的,如果文章是采集过来的,还是关闭的好,有很多关键字都毫无意义,甚至会有乱码导致生成出错,关掉此功能对提高系统性能是有一定帮助的。

3)数据库表索引优化 性能大幅提升

为什么要对DedeCMS数据库表索引进行优化呢?很简单,在Mysql中,索引无疑是最有效的加快查询的工具了,一个合理的索引组合会极大地提升 你的查询效率和系统性能。言归正传,你可以通过phpmyadmin或是一个叫Navicat for MySQL的软件(推荐)来管理你的数据库。

分析DEDECMS数据表信息,不难发现,所有的文章数据是存储在dede_archives和dede_arctiny,以及对应的 dede_addonarticle附加表中的。生成HTML时,sql查询主要围绕这三张表来的。个人认为,凡是要排序的字段和查询条件的字段及文档 ID都要建立索引,如果一个没有建立,将会严重影响MySQL的查询效率,最终导致生成速度变慢。DEDECMS数据表索引建立方法如下:

a)dede_archives,是文章的主表,存储文章标题、关键 字、描述、发布时间等信息,10万数据的表大小可能在30MB左右,也是我们优化的重点。你需要建立的索引字段有,id、channel、 pubdate、sortrank、ismake、typeid、mainindex、lastpost;其中,像系统默认的mainindex和 lastpost这两个组合索引,个人认为存在意义不大,可以删除,自己掂量。需要注意的是,click字段,是文档的点击数,此字段更新频率,建立索引 后会对系统维护带来一定压力,另外也有人说频繁更新的建立索引会容易导致数据库损坏,也无从查证。个人建议click字段保留,不建立索引。

b)dede_arctiny,这个表比较小,10万数据的表大小不到5MB,建议不建立索引,可以将自带的删除掉,或者只保留sortrank索引。

c)dede_addonarticle,是文章附加表,主要是用来存储文章内容的,不作索引考虑。

以上索引成功建立后,再测试下你的HTML生成速度,是不是让你精神一振呢?

4)搭建胜过Apache十倍的高并发Web服务器 Nginx + PHP(FastCGI)

Web服务器的重要性不需多言,对提升网站性能有着直接影响。在PHP开发中,最常用的环境莫过于在 LAMP:Linux+apache+mysql+php了,在windows下有 WAMP:Windows+apache/iis+mysql+php,我的WEB站点也是在这种环境下开发的。Nginx + PHP(FastCGI)无疑是你最好的选择,在Windows和Linux下都可以安装,只是Windows下的Nginx表现要远远逊色于Linux。

DedeCMS系统运行是依赖PHP+MYSQL环境的,所以说一个运行快、资源消耗小的Web服务器对提升系统性能有多重要。如果条件允许的条件,还是推荐下Nginx + PHP(FastCGI)这种WEB服务器环境。

以上就是DedeCMS数据负载性能的优化方案,针对的是有独立WEB服务器或控制权限的站长,至于虚拟主机想 达到这个速度还是很费劲的,但是也可以作为DedeCMS性能优化的一个参考依据,自己琢磨琢磨了。当然,如果有更好的提高DedeCMS数据负载性能的 办法,还希望分享下。其实,正常情况下(不包括采集),一般站点数据量也都有限,20万就很了不起了吧?我想,以上的DedeCMS优化方案足以解决了。 真到了百万级、千万级数据的时候,也不是一般站长需要考虑的事了。

您可能感兴趣的文章:
阅读全文