天天看點

mysql性能調優6_10個MySQL性能調優的方法

MYSQL 應該是最流行了 WEB 後端資料庫。WEB 開發語言最近發展很快,PHP, Ruby, Python, Java 各有特點,雖然 NOSQL 最近越來越多的被提到,但是相信大部分架構師還是會選擇 MYSQL 來做資料存儲。

MYSQL 如此友善和穩定,以至于我們在開發 WEB 程式的時候很少想到它。即使想到優化也是程式級别的,比如,不要寫過于消耗資源的 SQL 語句。但是除此之外,在整個系統上仍然有很多可以優化的地方。

1. 選擇合适的存儲引擎: InnoDB

除非你的資料表使用來做隻讀或者全文檢索 (相信現在提到全文檢索,沒人會用 MYSQL 了),你應該預設選擇 InnoDB 。

你自己在測試的時候可能會發現 MyISAM 比 InnoDB 速度快,這是因為: MyISAM 隻緩存索引,而 InnoDB 緩存資料和索引,MyISAM 不支援事務。但是 如果你使用 innodb_flush_log_at_trx_commit = 2 可以獲得接近的讀取性能 (相差百倍) 。

1.1 如何将現有的 MyISAM 資料庫轉換為 InnoDB:

複制代碼 代碼如下:

mysql -u [USER_NAME] -p -e "SHOW TABLES IN [DATABASE_NAME];" | tail -n +2 | xargs -I '{}' echo "ALTER TABLE {} ENGINE=InnoDB;" > alter_table.sql

perl -p -i -e 's/(search_[a-z_]+ ENGINE=)InnoDB//1MyISAM/g' alter_table.sql

mysql -u [USER_NAME] -p [DATABASE_NAME] < alter_table.sql

1.2 為每個表分别建立 InnoDB FILE:

複制代碼 代碼如下:

innodb_file_per_table=1

這樣可以保證 ibdata1 檔案不會過大,失去控制。尤其是在執行 mysqlcheck -o –all-databases 的時候。

2. 保證從記憶體中讀取資料,講資料儲存在記憶體中

2.1 足夠大的 innodb_buffer_pool_size

推薦将資料完全儲存在 innodb_buffer_pool_size ,即按存儲量規劃 innodb_buffer_pool_size 的容量。這樣你可以完全從記憶體中讀取資料,最大限度減少磁盤操作。

2.1.1 如何确定 innodb_buffer_pool_size 足夠大,資料是從記憶體讀取而不是硬碟?

方法 1

mysql> SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool_pages_%';

+----------------------------------+--------+

| Variable_name | Value |

+----------------------------------+--------+

| Innodb_buffer_pool_pages_data | 129037 |

| Innodb_buffer_pool_pages_dirty | 362 |

| Innodb_buffer_pool_pages_flushed | 9998 |

| Innodb_buffer_pool_pages_free | 0 | !!!!!!!!

| Innodb_buffer_pool_pages_misc | 2035 |

| Innodb_buffer_pool_pages_total | 131072 |

+----------------------------------+--------+

6 rows in set (0.00 sec)

發現 Innodb_buffer_pool_pages_free 為 0,則說明 buffer pool 已經被用光,需要增大 innodb_buffer_pool_size

InnoDB 的其他幾個參數:

複制代碼 代碼如下:

innodb_additional_mem_pool_size = 1/200 of buffer_pool

innodb_max_dirty_pages_pct 80%

方法 2

或者用iostat -d -x -k 1 指令,檢視硬碟的操作。

2.1.2 伺服器上是否有足夠記憶體用來規劃執行 echo 1 > /proc/sys/vm/drop_caches 清除作業系統的檔案緩存,可以看到真正的記憶體使用量。

2.2 資料預熱

預設情況,隻有某條資料被讀取一次,才會緩存在 innodb_buffer_pool。是以,資料庫剛剛啟動,需要進行資料預熱,将磁盤上的所有資料緩存到記憶體中。資料預熱可以提高讀取速度。

對于 InnoDB 資料庫,可以用以下方法,進行資料預熱:

1. 将以下腳本儲存為 MakeSelectQueriesToLoad.sql

SELECT DISTINCT

CONCAT('SELECT ',ndxcollist,' FROM ',db,'.',tb,

' ORDER BY ',ndxcollist,';') SelectQueryToLoadCache

FROM

(

SELECT

engine,table_schema db,table_name tb,

index_name,GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist

FROM

(

SELECT

B.engine,A.table_schema,A.table_name,

A.index_name,A.column_name,A.seq_in_index

FROM

information_schema.statistics A INNER JOIN

(

SELECT engine,table_schema,table_name

FROM information_schema.tables WHERE

engine='InnoDB'

) B USING (table_schema,table_name)

WHERE B.table_schema NOT IN ('information_schema','mysql')

ORDER BY table_schema,table_name,index_name,seq_in_index

) A

GROUP BY table_schema,table_name,index_name

) AA

ORDER BY db,tb

;

2. 執行

複制代碼 代碼如下:

mysql -uroot -AN < /root/MakeSelectQueriesToLoad.sql > /root/SelectQueriesToLoad.sql

3. 每次重新開機資料庫,或者整庫備份前需要預熱的時候執行:

mysql -uroot < /root/SelectQueriesToLoad.sql > /dev/null 2>&1

2.3 不要讓資料存到 SWAP 中

如果是專用 MYSQL 伺服器,可以禁用 SWAP,如果是共享伺服器,确定 innodb_buffer_pool_size 足夠大。或者使用固定的記憶體空間做緩存,使用 memlock 指令。

3. 定期優化重建資料庫

mysqlcheck -o –all-databases 會讓 ibdata1 不斷增大,真正的優化隻有重建資料表結構:

CREATE TABLE mydb.mytablenew LIKE mydb.mytable;

INSERT INTO mydb.mytablenew SELECT * FROM mydb.mytable;

ALTER TABLE mydb.mytable RENAME mydb.mytablezap;

ALTER TABLE mydb.mytablenew RENAME mydb.mytable;

DROP TABLE mydb.mytablezap;

4. 減少磁盤寫入操作

4.1 使用足夠大的寫入緩存 innodb_log_file_size

但是需要注意如果用 1G 的 innodb_log_file_size ,假如伺服器當機,需要 10 分鐘來恢複。

推薦 innodb_log_file_size 設定為 0.25 * innodb_buffer_pool_size

4.2 innodb_flush_log_at_trx_commit

這個選項和寫磁盤操作密切相關:

innodb_flush_log_at_trx_commit = 1 則每次修改寫入磁盤

innodb_flush_log_at_trx_commit = 0/2 每秒寫入磁盤

如果你的應用不涉及很高的安全性 (金融系統),或者基礎架構足夠安全,或者 事務都很小,都可以用 0 或者 2 來降低磁盤操作。

4.3 避免雙寫入緩沖

複制代碼 代碼如下:

innodb_flush_method=O_DIRECT

5. 提高磁盤讀寫速度

RAID0 尤其是在使用 EC2 這種虛拟磁盤 (EBS) 的時候,使用軟 RAID0 非常重要。

6. 充分使用索引

6.1 檢視現有表結構和索引

複制代碼 代碼如下:

SHOW CREATE TABLE db1.tb1/G

6.2 添加必要的索引

索引是提高查詢速度的唯一方法,比如搜尋引擎用的反向索引是一樣的原理。

索引的添加需要根據查詢來确定,比如通過慢查詢日志或者查詢日志,或者通過 EXPLAIN 指令分析查詢。

複制代碼 代碼如下:

ADD UNIQUE INDEX

ADD INDEX

6.2.1 比如,優化使用者驗證表:

添加索引

複制代碼 代碼如下:

ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);

ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);

每次重新開機伺服器進行資料預熱

複制代碼 代碼如下:

echo “select username,password from users;” > /var/lib/mysql/upcache.sql

添加啟動腳本到 my.cnf

複制代碼 代碼如下:

[mysqld]

init-file=/var/lib/mysql/upcache.sql

6.2.2 使用自動加索引的架構或者自動拆分表結構的架構比如,Rails 這樣的架構,會自動添加索引,Drupal 這樣的架構會自動拆分表結構。會在你開發的初期指明正确的方向。是以,經驗不太豐富的人一開始就追求從 0 開始建構,實際是不好的做法。

7. 分析查詢日志和慢查詢日志

記錄所有查詢,這在用 ORM 系統或者生成查詢語句的系統很有用。

複制代碼 代碼如下:

log=/var/log/mysql.log

注意不要在生産環境用,否則會占滿你的磁盤空間。

記錄執行時間超過 1 秒的查詢:

複制代碼 代碼如下:

long_query_time=1

log-slow-queries=/var/log/mysql/log-slow-queries.log

8. 激進的方法,使用記憶體磁盤

現在基礎設施的可靠性已經非常高了,比如 EC2 幾乎不用擔心伺服器硬體當機。而且記憶體實在是便宜,很容易買到幾十G記憶體的伺服器,可以用記憶體磁盤,定期備份到磁盤。

将 MYSQL 目錄遷移到 4G 的記憶體磁盤

mkdir -p /mnt/ramdisk

sudo mount -t tmpfs -o size=4000M tmpfs /mnt/ramdisk/

mv /var/lib/mysql /mnt/ramdisk/mysql

ln -s /tmp/ramdisk/mysql /var/lib/mysql

chown mysql:mysql mysql

9. 用 NOSQL 的方式使用 MYSQL

B-TREE 仍然是最高效的索引之一,所有 MYSQL 仍然不會過時。

用 HandlerSocket 跳過 MYSQL 的 SQL 解析層,MYSQL 就真正變成了 NOSQL。

10. 其他

單條查詢最後增加 LIMIT 1,停止全表掃描。

将非”索引”資料分離,比如将大篇文章分離存儲,不影響其他自動查詢。

不用 MYSQL 内置的函數,因為内置函數不會建立查詢緩存。

PHP 的建立連接配接速度非常快,所有可以不用連接配接池,否則可能會造成超過連接配接數。當然不用連接配接池 PHP 程式也可能将

連接配接數占滿比如用了 @ignore_user_abort(TRUE);

使用 IP 而不是域名做資料庫路徑,避免 DNS 解析問題

以上就是10個MySQL性能調優的方法,希望對大家的學習有所幫助。

本文标題: 10個MySQL性能調優的方法

本文位址: http://www.cppcns.com/shujuku/mysql/128753.html