程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 經由過程MySQL優化Discuz!的熱帖翻頁的技能

經由過程MySQL優化Discuz!的熱帖翻頁的技能

編輯:MySQL綜合教程

經由過程MySQL優化Discuz!的熱帖翻頁的技能。本站提示廣大學習愛好者:(經由過程MySQL優化Discuz!的熱帖翻頁的技能)文章只能為提供參考,不一定能成為您想要的結果。以下是經由過程MySQL優化Discuz!的熱帖翻頁的技能正文


寫在後面:discuz!作為數一數二的社區體系,為寬大站長供給了一站式網站處理計劃,並且是開源的(固然部門代碼是加密的),它為這個垂直范疇的行業成長作出了偉大進獻。雖然如斯,discuz!體系源碼中,照樣或多或少有些坑。個中最有名的就是默許采取MyISAM引擎,和基於MyISAM引擎的搶樓功效,session表采取memory引擎等,可以參考前面幾篇汗青文章。本次我們要說說discuz!在應對熱們帖子翻頁邏輯功效中的另外一個成績。

在我們的情況中,應用的是 MySQL-5.6.6 版本。

在檢查帖子並翻頁進程中,會發生相似上面如許的SQL:

mysql> desc SELECT * FROM pre_forum_post WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY dateline DESC LIMIT 15\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: pre_forum_post
 type: ref
 possible_keys: tid,displayorder,first
 key: displayorder
 key_len: 3
 ref: const
 rows: 593371
 Extra: Using index condition; Using where; Using filesort

這個SQL履行的價值是:

-- 依據索引拜訪行記載次數,整體而言算是比擬好的狀況

| Handler_read_key   | 16  |

-- 依據索引次序拜訪下一行記載的次數,平日是由於依據索引的規模掃描,或許全索引掃描,整體而言也算是比擬好的狀況

| Handler_read_next   | 329881 |

-- 依照必定次序讀取行記載的總次數。假如須要對成果停止排序,該值平日會比擬年夜。當產生全表掃描或許多表join沒法應用索引時,該值也會比擬年夜

| Handler_read_rnd   | 15  |

而當碰到熱帖須要往後翻許多頁時,例如:

mysql> desc SELECT * FROM pre_forum_post WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY dateline LIMIT 129860, 15\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: pre_forum_post
 type: ref
 possible_keys: displayorder
 key: displayorder
 key_len: 3
 ref: const
 rows: 593371
 Extra: Using where; Using filesort

這個SQL履行的價值則釀成了(可以看到Handler_read_key、Handler_read_rnd年夜了許多):

| Handler_read_key           | 129876 | -- 由於後面須要跳過許多行記載
| Handler_read_next          | 329881 | -- 同上
| Handler_read_rnd           | 129875 | -- 由於須要先對很年夜一個成果集停止排序

可見,碰到熱帖時,這個SQL的價值會異常高。假如該熱帖被年夜量的拜訪汗青答復,或許被搜素引擎一向重復要求而且汗青答復頁時,很輕易把數據庫辦事器直接壓垮。

小結:這個SQL不克不及應用 `displayorder` 索引排序的緣由是,索引的第二個列 `invisible` 采取規模查詢(RANGE),招致沒方法持續應用結合索引完成對 `dateline` 字段的排序需求(而假如是 WHERE tid =? AND invisible IN(?, ?) AND dateline =? 這類情形下是完整可以用到全部結合索引的,留意下兩者的差別)。

曉得了這個緣由,響應的優化處理方法也就清楚了:
創立一個新的索引 idx_tid_dateline,它只包含 tid、dateline 兩個列便可(依據其他索引的統計信息,item_type 和 item_id 的基數太低,所以沒包括在結合索引中。固然了,也能夠斟酌一並加上)。

我們再來看下采取新的索引後的履行籌劃:

mysql> desc SELECT * FROM pre_forum_post WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY dateline LIMIT 15\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: pre_forum_post
 type: ref
 possible_keys: tid,displayorder,first,idx_tid_dateline
 key: idx_tid_dateline
 key_len: 3
 ref: const
 rows: 703892
 Extra: Using where

可以看到,之前存在的 Using filesort 消逝了,可以經由過程索引直接完成排序了。

不外,假如該熱帖翻到較舊的汗青答復時,響應的SQL照樣不克不及應用新的索引:

mysql> desc SELECT * FROM pre_forum_post WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY dateline LIMIT 129860,15\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: pre_forum_post
 type: ref
 possible_keys: tid,displayorder,first,idx_tid_dateline
 key: displayorder
 key_len: 3
 ref: const
 rows: 593371
 Extra: Using where; Using filesort

比較下假如建議優化器應用新索引的話,其履行籌劃是如何的:

mysql> desc SELECT * FROM pre_forum_post use index(idx_tid_dateline) WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY dateline LIMIT 129860,15\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: pre_forum_post
 type: ref
 possible_keys: idx_tid_dateline
 key: idx_tid_dateline
 key_len: 3
 ref: const
 rows: 703892
 Extra: Using where

可以看到,由於查詢優化器以為後者須要掃描的行數遠比前者多了11萬多,是以以為前者效力更高。

現實上,在這個例子裡,排序的價值更高,是以我們要優先清除排序,所以應當強迫應用新的索引,也就是采取前面的履行籌劃,在響應的法式中指定索引。

最初,我們來看下熱帖翻到很老的汗青答復時,兩個履行籌劃分離的profiling統計信息比較:

1、采取舊索引(displayorder):

mysql> SELECT * FROM pre_forum_post WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY dateline LIMIT 129860,15;

#檢查profiling成果
 | starting    | 0.020203 |
 | checking permissions | 0.000026 |
 | Opening tables  | 0.000036 |
 | init     | 0.000099 |
 | System lock   | 0.000092 |
 | optimizing   | 0.000038 |
 | statistics   | 0.000123 |
 | preparing   | 0.000043 |
 | Sorting result  | 0.000025 |
 | executing   | 0.000023 |
 | Sending data   | 0.000045 |
 | Creating sort index | 0.941434 |
 | end     | 0.000077 |
 | query end   | 0.000044 |
 | closing tables  | 0.000038 |
 | freeing items  | 0.000056 |
 | cleaning up   | 0.000040 |

2、假如是采取新索引(idx_tid_dateline):

mysql> SELECT * FROM pre_forum_post use index(idx_tid_dateline) WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY dateline LIMIT 129860,15;

#比較檢查profiling成果
 | starting    | 0.000151 |
 | checking permissions | 0.000033 |
 | Opening tables  | 0.000040 |
 | init     | 0.000105 |
 | System lock   | 0.000044 |
 | optimizing   | 0.000038 |
 | statistics   | 0.000188 |
 | preparing   | 0.000044 |
 | Sorting result  | 0.000024 |
 | executing   | 0.000023 |
 | Sending data   | 0.917035 |
 | end     | 0.000074 |
 | query end   | 0.000030 |
 | closing tables  | 0.000036 |
 | freeing items  | 0.000049 |
 | cleaning up   | 0.000032 |

可以看到,效力有了必定進步,不外不是很顯著,由於確切須要掃描的數據量更年夜,所以 Sending data 階段耗時更多。

這時候候,我們可以再參考之前的一個優化計劃:[MySQL優化案例]系列 — 分頁優化

然後可以將這個SQL改寫成上面如許:

mysql> EXPLAIN SELECT * FROM pre_forum_post t1 INNER JOIN (
 SELECT id FROM pre_forum_post use index(idx_tid_dateline) WHERE
 tid=8201301 AND `invisible` IN('0','-2') ORDER BY
 dateline LIMIT 129860,15) t2
 USING (id)\G
 *************************** 1. row ***************************
 id: 1
 select_type: PRIMARY
 table: 
 type: ALL
 possible_keys: NULL
 key: NULL
 key_len: NULL
 ref: NULL
 rows: 129875
 Extra: NULL
 *************************** 2. row ***************************
 id: 1
 select_type: PRIMARY
 table: t1
 type: eq_ref
 possible_keys: PRIMARY
 key: PRIMARY
 key_len: 4
 ref: t2.id
 rows: 1
 Extra: NULL
 *************************** 3. row ***************************
 id: 2
 select_type: DERIVED
 table: pre_forum_post
 type: ref
 possible_keys: idx_tid_dateline
 key: idx_tid_dateline
 key_len: 3
 ref: const
 rows: 703892
 Extra: Using where

再看下這個SQL的 profiling 統計信息:

| starting    | 0.000209 |
| checking permissions | 0.000026 |
| checking permissions | 0.000026 |
| Opening tables  | 0.000101 |
| init     | 0.000062 |
| System lock   | 0.000049 |
| optimizing   | 0.000025 |
| optimizing   | 0.000037 |
| statistics   | 0.000106 |
| preparing   | 0.000059 |
| Sorting result  | 0.000039 |
| statistics   | 0.000048 |
| preparing   | 0.000032 |
| executing   | 0.000036 |
| Sending data   | 0.000045 |
| executing   | 0.000023 |
| Sending data   | 0.225356 |
| end     | 0.000067 |
| query end   | 0.000028 |
| closing tables  | 0.000023 |
| removing tmp table | 0.000029 |
| closing tables  | 0.000044 |
| freeing items  | 0.000048 |
| cleaning up   | 0.000037 |

可以看到,效力晉升了1倍以上,照樣挺不錯的。

最初解釋下,這個成績只會在熱帖翻頁時才會湧現,普通只要1,2頁答復的帖子假如還采取本來的履行籌劃,也沒甚麼成績。

是以,建議discuz!官方修正或增長下新索引,而且在代碼中斷定能否熱帖翻頁,是的話,就強迫應用新的索引,以免機能成績。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved