亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

通過(guò)MySQL優(yōu)化Discuz!的熱帖翻頁(yè)的技巧

 更新時(shí)間:2015年05月07日 16:43:24   作者:葉金榮  
這篇文章主要介紹了通過(guò)MySQL優(yōu)化Discuz!的熱帖翻頁(yè)的技巧,包括更新索引來(lái)降低服務(wù)器負(fù)載等方面,需要的朋友可以參考下

寫在前面:discuz!作為首屈一指的社區(qū)系統(tǒng),為廣大站長(zhǎng)提供了一站式網(wǎng)站解決方案,而且是開(kāi)源的(雖然部分代碼是加密的),它為這個(gè)垂直領(lǐng)域的行業(yè)發(fā)展作出了巨大貢獻(xiàn)。盡管如此,discuz!系統(tǒng)源碼中,還是或多或少有些坑。其中最著名的就是默認(rèn)采用MyISAM引擎,以及基于MyISAM引擎的搶樓功能,session表采用memory引擎等,可以參考后面幾篇?dú)v史文章。本次我們要說(shuō)說(shuō)discuz!在應(yīng)對(duì)熱們帖子翻頁(yè)邏輯功能中的另一個(gè)問(wèn)題。

在我們的環(huán)境中,使用的是 MySQL-5.6.6 版本。

在查看帖子并翻頁(yè)過(guò)程中,會(huì)產(chǎn)生類似下面這樣的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

這個(gè)SQL執(zhí)行的代價(jià)是:

-- 根據(jù)索引訪問(wèn)行記錄次數(shù),總體而言算是比較好的狀態(tài)

| Handler_read_key   | 16  |

-- 根據(jù)索引順序訪問(wèn)下一行記錄的次數(shù),通常是因?yàn)楦鶕?jù)索引的范圍掃描,或者全索引掃描,總體而言也算是比較好的狀態(tài)

| Handler_read_next   | 329881 |

-- 按照一定順序讀取行記錄的總次數(shù)。如果需要對(duì)結(jié)果進(jìn)行排序,該值通常會(huì)比較大。當(dāng)發(fā)生全表掃描或者多表join無(wú)法使用索引時(shí),該值也會(huì)比較大

| Handler_read_rnd   | 15  |

而當(dāng)遇到熱帖需要往后翻很多頁(yè)時(shí),例如:

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

這個(gè)SQL執(zhí)行的代價(jià)則變成了(可以看到Handler_read_key、Handler_read_rnd大了很多):

| Handler_read_key           | 129876 | -- 因?yàn)榍懊嫘枰^(guò)很多行記錄
| Handler_read_next          | 329881 | -- 同上
| Handler_read_rnd           | 129875 | -- 因?yàn)樾枰葘?duì)很大一個(gè)結(jié)果集進(jìn)行排序

可見(jiàn),遇到熱帖時(shí),這個(gè)SQL的代價(jià)會(huì)非常高。如果該熱帖被大量的訪問(wèn)歷史回復(fù),或者被搜素引擎一直反復(fù)請(qǐng)求并且歷史回復(fù)頁(yè)時(shí),很容易把數(shù)據(jù)庫(kù)服務(wù)器直接壓垮。

小結(jié):這個(gè)SQL不能利用 `displayorder` 索引排序的原因是,索引的第二個(gè)列 `invisible` 采用范圍查詢(RANGE),導(dǎo)致沒(méi)辦法繼續(xù)利用聯(lián)合索引完成對(duì) `dateline` 字段的排序需求(而如果是 WHERE tid =? AND invisible IN(?, ?) AND dateline =? 這種情況下是完全可以用到整個(gè)聯(lián)合索引的,注意下二者的區(qū)別)。

知道了這個(gè)原因,相應(yīng)的優(yōu)化解決辦法也就清晰了:
創(chuàng)建一個(gè)新的索引 idx_tid_dateline,它只包括 tid、dateline 兩個(gè)列即可(根據(jù)其他索引的統(tǒng)計(jì)信息,item_type 和 item_id 的基數(shù)太低,所以沒(méi)包含在聯(lián)合索引中。當(dāng)然了,也可以考慮一并加上)。

我們?cè)賮?lái)看下采用新的索引后的執(zhí)行計(jì)劃:

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 消失了,可以通過(guò)索引直接完成排序了。

不過(guò),如果該熱帖翻到較舊的歷史回復(fù)時(shí),相應(yīng)的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

對(duì)比下如果建議優(yōu)化器使用新索引的話,其執(zhí)行計(jì)劃是怎樣的:

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

可以看到,因?yàn)椴樵儍?yōu)化器認(rèn)為后者需要掃描的行數(shù)遠(yuǎn)比前者多了11萬(wàn)多,因此認(rèn)為前者效率更高。

事實(shí)上,在這個(gè)例子里,排序的代價(jià)更高,因此我們要優(yōu)先消除排序,所以應(yīng)該強(qiáng)制使用新的索引,也就是采用后面的執(zhí)行計(jì)劃,在相應(yīng)的程序中指定索引。

最后,我們來(lái)看下熱帖翻到很老的歷史回復(fù)時(shí),兩個(gè)執(zhí)行計(jì)劃分別的profiling統(tǒng)計(jì)信息對(duì)比:

1、采用舊索引(displayorder):

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

#查看profiling結(jié)果
 | 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;

#對(duì)比查看profiling結(jié)果
 | 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 |

可以看到,效率有了一定提高,不過(guò)不是很明顯,因?yàn)榇_實(shí)需要掃描的數(shù)據(jù)量更大,所以 Sending data 階段耗時(shí)更多。

這時(shí)候,我們可以再參考之前的一個(gè)優(yōu)化方案:[MySQL優(yōu)化案例]系列 — 分頁(yè)優(yōu)化

然后可以將這個(gè)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

再看下這個(gè)SQL的 profiling 統(tǒng)計(jì)信息:

| 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倍以上,還是挺不錯(cuò)的。

最后說(shuō)明下,這個(gè)問(wèn)題只會(huì)在熱帖翻頁(yè)時(shí)才會(huì)出現(xiàn),一般只有1,2頁(yè)回復(fù)的帖子如果還采用原來(lái)的執(zhí)行計(jì)劃,也沒(méi)什么問(wèn)題。

因此,建議discuz!官方修改或增加下新索引,并且在代碼中判斷是否熱帖翻頁(yè),是的話,就強(qiáng)制使用新的索引,以避免性能問(wèn)題。

相關(guān)文章

  • 分析Mysql事務(wù)和數(shù)據(jù)的一致性處理問(wèn)題

    分析Mysql事務(wù)和數(shù)據(jù)的一致性處理問(wèn)題

    本篇文章主要給大家介紹了Mysql事務(wù)和數(shù)據(jù)的一致性處理問(wèn)題,跟著小編一起學(xué)習(xí)下吧。
    2017-12-12
  • mysql如何利用binlog進(jìn)行數(shù)據(jù)恢復(fù)詳解

    mysql如何利用binlog進(jìn)行數(shù)據(jù)恢復(fù)詳解

    MySQL的binlog日志是MySQL日志中非常重要的一種日志,下面這篇文章主要給大家介紹了關(guān)于mysql如何利用binlog進(jìn)行數(shù)據(jù)恢復(fù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-10-10
  • MYSQL命令行導(dǎo)入導(dǎo)出數(shù)據(jù)庫(kù)詳解

    MYSQL命令行導(dǎo)入導(dǎo)出數(shù)據(jù)庫(kù)詳解

    這篇文章主要詳細(xì)介紹了MYSQL命令行進(jìn)行導(dǎo)入導(dǎo)出數(shù)據(jù)庫(kù)操作的方法,并且分win系統(tǒng)和Linux系統(tǒng)介紹了mysql備份和還原的方法,非常的詳細(xì),希望對(duì)大家能有所幫助
    2014-09-09
  • mysql如何查詢當(dāng)前數(shù)據(jù)庫(kù)中不為空的表

    mysql如何查詢當(dāng)前數(shù)據(jù)庫(kù)中不為空的表

    這篇文章主要介紹了mysql如何查詢當(dāng)前數(shù)據(jù)庫(kù)中不為空的表問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 往MySQL中存儲(chǔ)圖片的方法

    往MySQL中存儲(chǔ)圖片的方法

    這篇文章主要介紹了往MySQL中存儲(chǔ)圖片的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • mysql遠(yuǎn)程連接失敗的解決方法

    mysql遠(yuǎn)程連接失敗的解決方法

    在MySQL中,有時(shí)候我們需要遠(yuǎn)程連接到服務(wù)器來(lái)進(jìn)行操作,但是有時(shí)候,我們會(huì)遇到無(wú)法使用遠(yuǎn)程連接鏈接到MySQL服務(wù)器的情況,本文就介紹了兩種解決方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • mysql建表常用sql語(yǔ)句個(gè)人經(jīng)驗(yàn)分享

    mysql建表常用sql語(yǔ)句個(gè)人經(jīng)驗(yàn)分享

    熟悉一些常用的建表語(yǔ)句可以提升你建表的速度效率,本文整理了一些,個(gè)人感覺(jué)還不錯(cuò),希望對(duì)大家有所幫助
    2014-01-01
  • mysql無(wú)法啟動(dòng)服務(wù)及其他問(wèn)題總結(jié)

    mysql無(wú)法啟動(dòng)服務(wù)及其他問(wèn)題總結(jié)

    MySQL無(wú)法啟動(dòng),可能有多種原因?qū)е?本文主要介紹了mysql無(wú)法啟動(dòng)服務(wù)及其他問(wèn)題總結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • 如何用word vb宏來(lái)生成sql

    如何用word vb宏來(lái)生成sql

    本篇文章是對(duì)利用word vb宏來(lái)生成sql的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • MySQL刪除表時(shí)I/O錯(cuò)誤的原因分析與解決

    MySQL刪除表時(shí)I/O錯(cuò)誤的原因分析與解決

    這篇文章主要給大家介紹了關(guān)于MySQL刪除表時(shí)I/O錯(cuò)誤的原因分析與解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08

最新評(píng)論