測試數據是無心中獲得的企業黃頁的數據,數據量將近90萬,都是徹底真實的數據,測試使用的程序是 dedecms4.0版本,你問爲何不用dedecms5.1?那是由於咱們爲了優化,針對dedecms作了不少修改,若是使用 dedecms5.1,咱們懼怕收到法院傳票……,補充一句,如下的優化方法均能在dedecms5.1中使用,請在理解其原理的基礎上自行完成。
未優化前咱們測試發現主要有三個常常性的操做在dede大數據量的狀況下影響管理性能,分別是文檔生成、列表頁生成和欄目列出全部文章,咱們就針對這三個方面進行優化實踐。
如下是測試數據的基本信息:
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='列表頁面文件名稱' ismake=' no'/}。這個方案優勢在於僅增長部分操做步驟,沒有改動任何程序,性能提升亦很是明顯。下圖就是咱們利用這個方法優化後的生成速度,僅用時50秒就完成了1500多頁的文章生成,達成目標優化效果。此方案因爲增長了操做步驟,懶人慎用。
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_a**narticle on arc.ID = qiye_a**narticle.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用來記錄數據統計結果。程序修改以後,得到了滿意的效果。 php
http://zencart.me mysql