<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>枫子博客优化</title>
	<atom:link href="http://www.imfeng.com/tag/%e4%bc%98%e5%8c%96/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.imfeng.com</link>
	<description>很枫的那种 闲人请勿靠近</description>
	<lastBuildDate>Mon, 23 Aug 2010 02:40:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>DeDeCMS负载性能优化实例</title>
		<link>http://www.imfeng.com/dedecms-rated-load-optimize/</link>
		<comments>http://www.imfeng.com/dedecms-rated-load-optimize/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 23:27:36 +0000</pubDate>
		<dc:creator>枫子</dc:creator>
				<category><![CDATA[DeDeCMS]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[负载]]></category>

		<guid isPermaLink="false">http://www.imfeng.com/?p=41</guid>
		<description><![CDATA[最近对dedecms二次开发的很厉害。
用手机上网找的，马上保存。 原文来源不详

对dedecms表现出来的相对较差的性能也感觉比较迷惑，到底是什么在制约其负载效率？难道真的是某些脑残的dede论坛版主说的是因为mysql不堪重负的原因吗？
还是因为一个表的大数据造成性能严重下降?难道我们必须通过分多个表来存储才能解决问题吗?以下我们通过一个实例来解析和优化dedecms的数据管理性能，千万别让mysql当替罪羊，罪莫大焉。
　　测试数据是无意中得到的企业黄页的数据，数据量将近90万，都是完全真实的数据，测试使用的程序是dedecms4.0版本，你问为什么不用dedecms5.1?那是因为我们为了优化，针对dedecms做了很多修改，如果使用dedecms5.1，我们害怕收到法院传票……，补充一句，以下的优化方法均能在dedecms5.1中使用，请在理解其原理的基础上自行完成。
　　未优化前我们测试发现主要有三个经常性的操作在dede大数据量的情况下影响管理性能，分别是文档生成、列表页生成和栏目列出所有文章，我们就针对这三个方面进行优化实践。
　　以下是测试数据的基本信息：
　　每个栏目包含近3万数据
1.改进文档生成速度
问题提出
　　和我们前一次测评结果相同，dedecms的文档的生成速度惨不忍睹。使用默认模板(article_article.htm)，平均接近30秒才能生成20个页面(如图)，按照这个速度生成下去，90万的数据全部生成网页能等到头发都白了。那么到底问题在哪里呢?
　　问题分析
　　先排除表索引的问题，因为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=&#8217;列表页面文件名称&#8217; ismake=&#8217; no&#8217;/}。这个方案优点在于仅增加部分操作步骤，没有改动任何程序，性能提高亦非常明显。下图就是我们利用这个方法优化后的生成速度，仅用时50秒就完成了1500多页的文章生成，达成目标优化效果。此方案由于增加了操作步骤，懒人慎用。
　　优化前的列表页面生成速度
　　问题分析
　　由于目标锁定在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 &#62; -1 And ( ( arc.typeid=&#8217;1′ ) or arc.typeid2=&#8217;1′) order by arc.sortrank desc limit 0,50
　　我们注意到这个SQL语句中的where子句使用了and和or的多种条件判断，经验告诉我们如果查询子句中使用了in或者or语句，会导致全表扫描，这样的话索引的效率就无法体现。我们简化了where子句的判断条件进行测试，结果发现删除了or子句之后，查询效率大幅提升，上面的查询语句只用时不到1秒就获得了查询结果。这就是问题关键。
　　解决问题
　　对于list查询来说，arc.typeid2=&#8217;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-&#62;dsql-&#62;Query();
　　$this-&#62;totalResult = $this-&#62;dsql-&#62;GetTotalRow();
　　这里所用的数据总数统计的方式居然是通过content_list.php传递过来一个复杂的查询语句，然后执行这个查询并将结果保存到数据集中，最后通过mysql_num_rows函数统计结果集中行的数目，完全没有想到dedecms居然走了一个最远的路途完成一个最简单的操作，难怪效率低得可怕。因此只要我们改用最常见的count方法来统计数据，执行效率就能大幅提高。
　　解决问题
　　首先我们修改了程序content_list.php，构造了$conutquery参数用来保存统计使用的SQL语句，代码如下：
　　……
　　$conutquery=”
　　select count(*) as totalResult
　　from dede_archives
　　left join dede_arctype on dede_arctype.ID=dede_archives.typeid
　　left join [...]]]></description>
			<content:encoded><![CDATA[<p>最近对dedecms二次开发的很厉害。</p>
<p>用手机上网找的，马上保存。 原文来源不详<span id="more-41"></span></p>
<div>
<p>对dedecms表现出来的相对较差的性能也感觉比较迷惑，到底是什么在制约其负载效率？难道真的是某些脑残的dede论坛版主说的是因为mysql不堪重负的原因吗？<br />
还是因为一个表的大数据造成性能严重下降?难道我们必须通过分多个表来存储才能解决问题吗?以下我们通过一个实例来解析和优化dedecms的数据管理性能，千万别让mysql当替罪羊，罪莫大焉。</p>
<p>　　测试数据是无意中得到的企业黄页的数据，数据量将近90万，都是完全真实的数据，测试使用的程序是dedecms4.0版本，你问为什么不用dedecms5.1?那是因为我们为了优化，针对dedecms做了很多修改，如果使用dedecms5.1，我们害怕收到法院传票……，补充一句，以下的优化方法均能在dedecms5.1中使用，请在理解其原理的基础上自行完成。</p>
<p>　　未优化前我们测试发现主要有三个经常性的操作在dede大数据量的情况下影响管理性能，分别是文档生成、列表页生成和栏目列出所有文章，我们就针对这三个方面进行优化实践。</p>
<p>　　以下是测试数据的基本信息：</p>
<p>　　每个栏目包含近3万数据</p>
<p>1.改进文档生成速度<br />
问题提出</p>
<p>　　和我们前一次测评结果相同，dedecms的文档的生成速度惨不忍睹。使用默认模板(article_article.htm)，平均接近30秒才能生成20个页面(如图)，按照这个速度生成下去，90万的数据全部生成网页能等到头发都白了。那么到底问题在哪里呢?</p>
<p>　　问题分析</p>
<p>　　先排除表索引的问题，因为dede的数据库已经在数据主表(dede_archives)为主要字段都建立了索引。再排除主要内容的提取效率问题，因为页面生成过程中读取页面中的文章数据，每次需要到主表和附表中select取得id值唯一的数据内容，这个SQL语句的效率我们通过直接在mysql中运行SQL语句测试，执行时间非常短，因此这也不是最大的瓶颈。</p>
<p>　　终于在页面生成过程中，我们发现程序执行了数次主表(dede_archives)查询，并取出符合一组复杂查询条件数据的操作，查询效率非常低，原来是它在影响效率!通过调试跟踪，我们定位了问题的关键，元凶就是模板中arclist标签。Arclist标签是很多人很喜欢用的标签，因为它比较灵活，能从数据中取出热门、最新、相关等各种类型的文章列表，但是arclist标签每次都会带着一大推搜索条件去主表中查询，实际上对于一次性生成大量文章来说，如果使用相同的模板，arclist对数据库的查询操作只是简单机械重复罢了，为此而耗费了大量时间绝对是不值得的。接下来我们给出问题解决的建议。</p>
<p>　　解决问题</p>
<p>　　解决方案1：去掉最终页面模板中的arclist标签，或者尽可能少用。这个方法虽然能极大提高效率，但是无异于泼水把孩子泼走了，对于企图增加访问pv的网站来说，不建议使用。</p>
<p>　　解决方案2：建立arclist缓存，将每次arclist生成的数据放到临时目录或者缓存当中，在文档生成过程中判断缓存是否有更新，如果无更新，直接使用缓存数据。这个方法无需改变模板，对于提高生成效率也有一定的效果，但由于对程序改动较大，酌情考虑使用。</p>
<p>　　解决方案3：也是小组建议的解决方案，那就是充分挖掘现有dedecms的功能，在尽量不改变程序的基础上，大幅提高效率。具体的方法就是通过freelist(自由列表生成)功能事先生成热门文章、最新文章、相关文章等内容的列表页面，然后使用dedecms提供的include标签直接引入文档页面。标签格式为：{dede:include file=&#8217;列表页面文件名称&#8217; ismake=&#8217; no&#8217;/}。这个方案优点在于仅增加部分操作步骤，没有改动任何程序，性能提高亦非常明显。下图就是我们利用这个方法优化后的生成速度，仅用时50秒就完成了1500多页的文章生成，达成目标优化效果。此方案由于增加了操作步骤，懒人慎用。</p>
<p>　　优化前的列表页面生成速度</p>
<p>　　问题分析</p>
<p>　　由于目标锁定在list标签，测试的过程就简单了。我们直接使用dedecms中list的查询语句做优化分析，很快发现了问题。我们测试了list中的sql查询语句，以下代码就是list用来查询数据库中对应条件的SQL语句，执行时间大约为15秒，效率很不理想。</p>
<p>　　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 &gt; -1 And ( ( arc.typeid=&#8217;1′ ) or arc.typeid2=&#8217;1′) order by arc.sortrank desc limit 0,50</p>
<p>　　我们注意到这个SQL语句中的where子句使用了and和or的多种条件判断，经验告诉我们如果查询子句中使用了in或者or语句，会导致全表扫描，这样的话索引的效率就无法体现。我们简化了where子句的判断条件进行测试，结果发现删除了or子句之后，查询效率大幅提升，上面的查询语句只用时不到1秒就获得了查询结果。这就是问题关键。</p>
<p>　　解决问题</p>
<p>　　对于list查询来说，arc.typeid2=&#8217;1′这个条件目的是查找某个文章所属的第二分类，而事实上这个功能在大部分情况下很少使用，因为我们大可使用标签(tag)来完成一篇文章的多个不同分类的归属，因此我们修改文件inc_arclist_view.php，在查询语句中直接删除了typeid2的条件判断，并在pub_db_mysql.php中改进了查询执行函数(主要用于提高sql语句执行的效率，对最终结果影响不大)，得到的最终测试结果如下，平均每个列表页面的生成时间下讲到不到1秒，3万数据600个列表页面生成只需要花费不到10分钟，优化目标达成。</p>
<p>　　3.改进文档管理效率</p>
<p>　　问题提出</p>
<p>　　在90万这个数据量的情况下，dedecms打开栏目文章列表，尤其是打开所有档案列表企图进行文章管理的时候，速度简直无法让人忍受。我们点击所有文档列表，耐着性子等了将近2分钟，文章列表页面才姗姗来迟。到底什么在制约着文章列表速度呢?</p>
<p>　　优化前使用所有档案列表数据加载完成时间<br />
分析问题<br />
 </p>
<p>　　控制显示文档列表的程序是dede/content_list.php和include/pub_datalist_dm.php，其中content_list.php是主控制程序，完成列表的参数传递和模板显示，而pub_datalist_dm.php用于完成数据查询和分页等操作。通过程序调试，我们找到了问题的结症在于pub_datalist_dm.php程序中对于全部数据的统计花费了大量的时间，而使用limit的列表数据的查询并不是性能的瓶颈。影响效率的关键代码为：</p>
<p>　　$this-&gt;dsql-&gt;Query();</p>
<p>　　$this-&gt;totalResult = $this-&gt;dsql-&gt;GetTotalRow();</p>
<p>　　这里所用的数据总数统计的方式居然是通过content_list.php传递过来一个复杂的查询语句，然后执行这个查询并将结果保存到数据集中，最后通过mysql_num_rows函数统计结果集中行的数目，完全没有想到dedecms居然走了一个最远的路途完成一个最简单的操作，难怪效率低得可怕。因此只要我们改用最常见的count方法来统计数据，执行效率就能大幅提高。</p>
<p>　　解决问题</p>
<p>　　首先我们修改了程序content_list.php，构造了$conutquery参数用来保存统计使用的SQL语句，代码如下：</p>
<p>　　……</p>
<p>　　$conutquery=”</p>
<p>　　select count(*) as totalResult</p>
<p>　　from dede_archives</p>
<p>　　left join dede_arctype on dede_arctype.ID=dede_archives.typeid</p>
<p>　　left join dede_channeltype on dede_channeltype.ID=dede_archives.channel</p>
<p>　　left join dede_admin on dede_admin.ID=dede_archives.adminID</p>
<p>　　$whereSql</p>
<p>　　order by dede_archives.{$orderby} desc”;</p>
<p>　　……</p>
<p>　　然后将这个参数和查询$query参数一起传递给pub_datalist_dm.php进行处理。</p>
<p>　　$dlist-&gt;SetSource($query,$conutquery);</p>
<p>　　随后将pub_datalist_dm.php中获得数据总数统计的代码替换为使用$conutquery参数：</p>
<p>　　……</p>
<p>　　//统计优化</p>
<p>　　$row = $this-&gt;dsql-&gt;GetOneSimple($this-&gt;countSql);</p>
<p>　　$this-&gt;totalResult = $row['totalResult'];</p>
<p>　　……</p>
<p>　　其中GetOneSimple是新构造的一个用来执行SQL语句的函数，我把它放在了pub_db_mysql.php类里面，主要的用途就是返回SQL语句执行结果, $this-&gt;countSql是上一个程序传递过来的统计使用的SQL代码，$this-&gt;totalResult用来记录数据统计结果。程序修改之后，获得了满意的效果。</p>
<p>　　总结</p>
<p>　　通过对以上几步优化操作，现在我们的程序后台已经能够非常轻松的应付90万数据的管理和维护了，事实证明dedecms的负载性能的瓶颈并不是mysql、服务器或者操作系统平台等，如果把未经优化的程序放到oracle的数据库上，使用更高级别的服务器，使用freebsd的操作系统，表现一样会不尽如人意。细节决定成败，看起来dedecms必须要在程序调优、性能优化上好好下功夫了。<br />
 </p></div>
Here is no comments yet by the time  your rss reader get this, Do you want to be the first commentor? Hurry up ]]></content:encoded>
			<wfw:commentRss>http://www.imfeng.com/dedecms-rated-load-optimize/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
