2007年3月我發現 discuz 論壇的數據庫結構設計有一些疏忽,有許多查詢子句的條件比較,都沒有建立 Index 索引。當時我所檢查的那個數據表,記錄只有幾千條,因此對 CPU 負荷不大。現在這個數據庫表,上千萬的記錄檢索,可以想象,如果數據表結構設計不規范,沒有提供索引,所耗費的時間是一個恐怖的數字。有關 MySQL 建立索引的重要性,可以參見我的這篇文章底部的說明
為了調試方便,我從 dizcus 的官網下載了其最新的 Dizcus! 5.5.0 論壇程序.
我首先檢查了 my.ini 的參數配置,一切正常。進入 MySQL 的命令行,調用 show processlist 語句,查找負荷最重的 SQL 語句,結合 Discuz 論壇的源碼,發現有以下語句導致 CPU 上升:
復制代碼 代碼如下:
mysql> show processlist; +-----+------+----------------+---------+---------+------+------------+--------- -----------------------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info
+-----+------+----------------+---------+---------+------+------------+--------- -----------------------------------------------------------------+ | 363 | root | localhost:1393 | history | Query | 0 | statistics | SELECT C OUNT(*) FROM cdb_pms WHERE msgfromid=11212 AND folder='outbox' | +-----+------+----------------+---------+---------+------+------------+---------
檢查 cdb_pms 表的結構:
復制代碼 代碼如下:
mysql> show columns from cdb_pms; +-----------+------------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+------------------------+------+-----+---------+----------------+ | pmid | int(10) unsigned | NO | PRI | NULL | auto_increment | | msgfrom | varchar(15) | NO | | | | | msgfromid | mediumint(8) unsigned | NO | MUL | 0 | | | msgtoid | mediumint(8) unsigned | NO | MUL | 0 | | | folder | enum('inbox','outbox') | NO | | inbox | | | new | tinyint(1) | NO | | 0 | | | subject | varchar(75) | NO | | | | | dateline | int(10) unsigned | NO | | 0 | | | message | text | NO | | | | | delstatus | tinyint(1) unsigned | NO | | 0 | | +-----------+------------------------+------+-----+---------+----------------+ 10 rows in set (0.00 sec)