摘要: https://edu.aliyun.com/a/29036?spm=5176.11182482.related_article.1.hbeZbFmysql
摘要: MYSQL 應該是最流行了 WEB 後端數據庫。WEB 開發語言最近發展很快,PHP, Ruby, Python, Java 各有特色,雖然 NOSQL 最近越來越多的被提到,可是相信大部分架構師仍是會選擇 MYSQL 來作數據存儲。MYSQL 如此方便和穩定,以致於咱們在開發 WEB 程序的時候不多想到它。即便想到優化也是程序級別的,好比,不要寫過於消耗資源的 SQL 語句。可是除此以外,在整...ios
MYSQL 應該是最流行了 WEB 後端數據庫。WEB 開發語言最近發展很快,PHP, Ruby, Python, Java 各有特色,雖然 NOSQL 最近越來越多的被提到,可是相信大部分架構師仍是會選擇 MYSQL 來作數據存儲。sql
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.sql1.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>&12.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_DIRECT5. 提升磁盤讀寫速度
RAID0 尤爲是在使用 EC2 這種虛擬磁盤 (EBS) 的時候,使用軟 RAID0 很是重要。
6. 充分使用索引 6.1 查看現有表結構和索引SHOW CREATE TABLE db1.tb1/G
6.2 添加必要的索引
索引是提升查詢速度的惟一方法,好比搜索引擎用的倒排索引是同樣的原理。
索引的添加須要根據查詢來肯定,好比經過慢查詢日誌或者查詢日誌,或者經過 EXPLAIN 命令分析查詢。
ADD UNIQUE INDEX ADD INDEX6.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.sql6.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.log8. 激進的方法,使用內存磁盤
如今基礎設施的可靠性已經很是高了,好比 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 mysql9. 用 NOSQL 的方式使用 MYSQL
B-TREE 仍然是最高效的索引之一,全部 MYSQL 仍然不會過期。
用 HandlerSocket 跳過 MYSQL 的 SQL 解析層,MYSQL 就真正變成了 NOSQL。
10. 其餘 單條查詢最後增長 LIMIT 1,中止全表掃描。以上是互聯網用戶爲您的的內容,在阿里雲內部有更多的關於MySQL性能調優的10個方法 - mysql數據庫欄目的內容,歡迎繼續使用右上角搜索按鈕進行搜索方法、性能、以便於您獲取更多的相關信息。