《Mysql入門MySQL針對Discuz論壇程序的基本優化教程》要點:
本文介紹了Mysql入門MySQL針對Discuz論壇程序的基本優化教程,希望對您有用。如果有疑問,可以聯系我們。
MYSQL學習過了這么久,discuz論壇的問題還是困擾著很多網友,其實從各論壇里看到的問題總結出來,很關鍵的一點都是因為沒有將數據表引擎轉成InnoDB導致的,discuz在并發稍微高一點的環境下就表現的非常糟糕,產生大量的鎖等待,這時候如果把數據表引擎改成InnoDB的話,我相信會好很多.這次就寫個掃盲貼吧.
MYSQL學習1. 啟用innodb引擎,并配置相關參數
MYSQL學習
#skip-innodb
MYSQL學習
innodb_additional_mem_pool_size = 16M #一般16M也夠了,可以適當調整下
innodb_buffer_pool_size = 6G #如果是專用db的話,一般是內存總量的80%
innodb_data_file_path = ibdata1:1024M:autoextend
innodb_file_io_threads = 4
innodb_thread_concurrency = 20
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 16M
innodb_log_file_size = 256M
innodb_log_files_in_group = 3
innodb_max_dirty_pages_pct = 50
innodb_lock_wait_timeout = 120
innodb_file_per_table
MYSQL學習修改表引擎為innodb:
MYSQL學習
mysql> alter table cdb_access engine = innodb;
MYSQL學習其他表類似上面,把表名換一下即可...
將表存儲引擎改成innodb后,不僅可以避免大量的鎖等待,還可以提升查詢的效率,因為innodb會把data和index都放在buffer pool中,效率更高.
MYSQL學習2.緩存優化
在 my.cnf 中添加/修改以下選項:
MYSQL學習
#取消文件系統的外部鎖
skip-locking
#不進行域名反解析,注意由此帶來的權限/授權問題
skip-name-resolve
#索引緩存,根據內存大小而定,如果是獨立的db服務器,可以設置高達80%的內存總量
key_buffer = 512M
#連接排隊列表總數
back_log = 200
max_allowed_packet = 2M
#打開表緩存總數,可以避免頻繁的打開數據表產生的開銷
table_cache = 512
#每個線程排序所需的緩沖
sort_buffer_size = 4M
#每個線程讀取索引所需的緩沖
read_buffer_size = 4M
#MyISAM表發生變化時重新排序所需的緩沖
myisam_sort_buffer_size = 64M
#緩存可重用的線程數
thread_cache = 128
#查詢結果緩存
query_cache_size = 128M
#設置超時時間,能避免長連接
set-variable = wait_timeout=60
#最大并發線程數,cpu數量*2
thread_concurrency = 4
#記錄慢查詢,然后對慢查詢一一優化
log-slow-queries = slow.log
long_query_time = 1
#關閉不需要的表類型,如果你需要,就不要加上這個
skip-bdb
MYSQL學習以上參數根據各自服務器的配置差異進行調整,僅作為參考.
MYSQL學習3.索引優化
上面提到了,已經開啟了慢查詢,那么接下來就要對慢查詢進行逐個優化了.
MYSQL學習搜索的查詢SQL大致如下:
MYSQL學習
SELECT t.* FROM cdb_posts p, cdb_threads t WHERE
t.fid IN ('37', '45', '4', '6', '17', '41', '28', '32', '31', '1', '42')
AND p.tid=t.tid AND p.author LIKE 'JoansWin'
GROUP BY t.tid ORDER BY lastpost DESC LIMIT 0, 80;
MYSQL學習用 EXPLAIN 分析的結果如下:
MYSQL學習
mysql>EXPLAIN SELECT t.* FROM cdb_posts p, cdb_threads t WHERE
t.fid IN ('37', '45', '4', '6', '17', '41', '28', '32', '31', '1', '42')
AND p.tid=t.tid AND p.author LIKE 'JoansWin'
GROUP BY t.tid ORDER BY lastpost DESC LIMIT 0, 80;
MYSQL學習
+-----------+------------+----------+--------------+-------------+-----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
+-----------+------------+----------+--------------+-------------+-----------+-------------+
| 1 | SIMPLE | t | range | PRIMARY,fid | fid | 2 | NULL | 66160 | Using where;
Using temporary; Using filesort |
| 1 | SIMPLE | p | ref | tid | tid | 3 | Forum.t.tid | 10 | Using where
| +----+-------------+-------+-------+---------------+------+---------+-------------+-------+
---------
MYSQL學習只用到了 t.fid 和 p.tid,而 p.author 則沒有索引可用,總共需要掃描
66160*10 = 661600 次索引,夠夸張吧 :(
再分析 cdb_threads 和 cdb_posts 的索引情況:
MYSQL學習
mysql>show index from cdb_posts;
MYSQL學習
+-----------+------------+----------+--------------+-------------+-----------+----------
---+----------+--------+------+--+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part |
Packed | Null | Index_type | Comment | +-----------+------------+----------+--------------+----
---------+-----------+-------------+----------+--------+------+--+
| cdb_posts | 0 | PRIMARY | 1 | pid | A | 680114 | NULL | NULL |
| BTREE | |
| cdb_posts | 1 | fid | 1 | fid | A | 10 | NULL | NULL |
| BTREE | |
| cdb_posts | 1 | tid | 1 | tid | A | 68011 | NULL | NULL |
| BTREE | |
| cdb_posts | 1 | tid | 2 | dateline | A | 680114 | NULL | NULL |
| BTREE | |
| cdb_posts | 1 | dateline | 1 | dateline | A | 680114 | NULL | NULL |
| BTREE | |
+-----------+------------+----------+--------------+-------------+-----------+---
MYSQL學習以及
MYSQL學習
mysql>show index from cdb_threads;
MYSQL學習
+-----------+------------+----------+--------------+-------------+-----------+-------------+
----------+--------+------+-----+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part |
Packed | Null | Index_type | Comment | +-----------+------------+----------+--------------+-----
--------+-----------+-------------+----------+--------+------+-----+
| cdb_threads | 0 | PRIMARY | 1 | tid | A | 68480 | NULL | NULL |
| BTREE | |
| cdb_threads | 1 | lastpost | 1 | topped | A | 4 | NULL | NULL |
| BTREE | |
| cdb_threads | 1 | lastpost | 2 | lastpost | A | 68480 | NULL | NULL |
| BTREE | |
| cdb_threads | 1 | lastpost | 3 | fid | A | 68480 | NULL | NULL |
| BTREE | |
| cdb_threads | 1 | replies | 1 | replies | A | 233 | NULL | NULL |
| BTREE | |
| cdb_threads | 1 | dateline | 1 | dateline | A | 68480 | NULL | NULL |
| BTREE | |
| cdb_threads | 1 | fid | 1 | fid | A | 10 | NULL | NULL |
| BTREE | |
| cdb_threads | 1 | enablehot | 1 | enablehot | A | 2 | NULL | NULL |
| BTREE | | +-------------+------------+-----------+--------------+-------------+------
MYSQL學習看到索引 fid 和 enablehot 基數太小,看來該索引完全沒必要,不過,對于fid基數較大的情況,則可能需要保留>該索引.
所做修改如下:
MYSQL學習
ALTER TABLE `cdb_threads` DROP INDEX `enablehot`, DROP INDEX `fid`, ADD INDEX (`fid`, `lastpost`);
ALTER TABLE `cdb_posts` DROP INDEX `fid`, ADD INDEX (`author`(10));
OPTIMIZE TABLE `cdb_posts`;
OPTIMIZE TABLE `cdb_threads`;
MYSQL學習在這里, p.author 字段我設定的部分索引長度是 10, 是我經過分析后得出來的結果,不同的系統,這里的長度也不同,最好自己先取一下平均值,然后再適當調整.
現在,再來執行一次上面的慢查詢,發現時間已經從 6s 變成 0.19s,提高了 30 倍.
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/3896.html