MySQL 性能優化 方案總結

原文

可以從以下幾個方面對MySQL進行優化, 

效果: SQL和索引 > 數據庫表結構 > 系統配置 > 硬件 
但成本從低到高。

1.SQL和索引優化

1.1SQL
1.1.1優化SQL語句的一般步驟:

①通過show status 命令瞭解各種SQL的執行效率,

show [session | global] status;
  • 1

可以根據需要加上參數來顯示session級(當前連接,默認)和global級(自數據庫上次啓動至今)的統計結果。 
eg:

 show status like 'Com_%';
  • 1

顯示當前連接所有統計參數的值。 
Com_xxx表示每個xxx語句執行的次數,通常需要注意的是下面幾個參數: 
Com_select/Com_insert/Com_update/Com_delte。

②定位執行效率較低的SQL語句 
·通過show processlist命令實時查看當前SQL的執行情況; 
·通過慢查詢日誌(結束以後記錄)定位出現的問題。

③通過explain 或 desc分析低效SQL的執行計劃 
select_type(simple/primary/union/subquery)/table/type/possible_keys/key/key_len/rows/extra

④通過show profile 分析SQL 
show profile 能幫我們瞭解時間都耗費到哪裏去了。 
MySQL從5.0.37版本開始增加了show profile和show profiles語句的支持, 
通過secect @have_profiling命令能夠看到當前MySQL是否支持profile, 
通過show profiles我們能夠更清楚瞭解SQL執行的過程, 
通過show profile for query我們能看到執行過程中線程的每個狀態和消耗的時間。

⑤通過trace分析優化器如何選擇執行計劃 
MySQL5.6提供了對SQL的跟蹤trace,能幫我們瞭解爲什麼優化器選擇執行A計劃而不是B計劃,進一步理解優化器的行爲。

⑥確定問題並採取相應的優化措施

1.1.2兩個簡單實用的優化方法

①定期分析和檢查表

analyze table tbl_name;
check table tbl_name;
  • 1
  • 2

②定期優化表

optimize table tbl_name;
  • 1
1.1.3常用SQL的優化

①優化insert語句 
·如果從同一客戶端插入很多行,應該儘量使用多個值表一次性插入; 
·如果從不同客戶端插入很多行,可以使用insert delayed語句先把數據放在內存的隊列中,並不真正寫入磁盤,比每條語句分別插入快得多; 
·當從一個文本文件裝載一個表時,使用load data infile,這通常比使用很多insert 語句快20倍; 
·如果在MyISAM表中進行批量插入,可以通過增加bulk_insert_buffer_size變量值的方法來提高速度。

②優化 order by語句 
MySQL中有兩種排序方式,第一種通過有序索引順序掃描直接返回有效數據,不需要額外的排序,操作效率較高;第二種對返回的數據進行排序,也就是常說的Filesort排序,所有不是通過索引直接返回排序結果的排序都是filesort排序。 
優化目標:儘量通過索引直接返回有序數據,減少額外的排序。 
通過創建合適的索引能減少filesort出現,但是某些情況下,條件限制不能讓filesort消失,那就需要想辦法加快filesort的操作。filesort有兩種排序算法,一種是一次掃描算法(較快),二種是兩次掃描算法。適當加大系統變量max_length_for_sort_data的值,能夠讓MySQL選擇更優化的filesort排序算法;適當加大sort_buffer_size排序區,儘量讓排序在內存中完成,而不是通過創建臨時表放在文件中進行。儘量只使用必要的字段,select具體的字段名稱,而不是select * 選擇所有字段,這樣可以減少排序區的使用,提高SQL性能。

③優化group by 語句 
MySQL默認對所有group by col1,col2…的字段進行排序,可以指定order by null禁止排序。

④優化嵌套查詢 
MySQL5.5及以下版本,子查詢的效率不如連接查詢(join),因爲MySQL不需要在內存中創建臨時表來完成這個在邏輯上需要兩個步驟的查詢工作。

⑤優化or 查詢 
對於含有or的查詢子句,如果要利用索引,則or之間的每個條件列都必須使用索引;如果沒有索引,可以考慮增加索引。 
MySQL在處理含有or的查詢時,實際上對or的各個字段分別查詢後的結果進行了union操作。

⑥優化分頁查詢 
·第一種 在索引上完成排序分頁操作,然後根據主鍵關聯回原表查詢所需要的其他列的內容; 
·第二種 在排序字段不會出現重複值的情況下,新增一個參數記錄上次查詢的最後一條記錄,將limit m,n轉化成limit n.

⑦使用SQL提示 
就是在SQL語句中加入一些認爲提示,讓MySQL按照特定方案執行,以達到優化操作的目的。 
·use index 指定MySQL參考的索引而忽略別的索引 
·ignore index 讓MySQL忽略某個或某些索引 
·force index 強制MySQL使用某個特定的索引

⑧其他 
·使用REGEXP,比如代替like. 
·使用rand()提取隨機行 
·表的字段儘量不使用自增長變量,在高併發的情況下可能會對MySQL的效率有較大影響。

1.2索引優化

MySQL的索引在存儲引擎層實現,而不是在服務器層。 
可以通過show status like ‘Handler_read%’命令來查看索引使用情況。

1.2.1MySQL 中索引的存儲類型目前有四種(B-Tree、Hash、空間索引R-Tree、全文索引Full-text),具體和表的存儲引擎相關;MyISAM 和 InnoDB 存儲引擎都支持 B-Tree 和全文索引(Full-text,InnoDB 5.6 +);MyISAM還支持空間索引(R-Tree);Memory/Heap存儲引擎可以支持 HASH和 B-Tree 索引,不過只有Memory/Heap支持 Hash索引。
1.2.2MySQL如何使用索引

(1)MySQL使用索引的典型情景 
①匹配全值(match the full value) 
②匹配值的範圍(match a range of values) 
③匹配最左前綴(match a leftmost prefix)最左匹配原則是MySQL中B-Tree索引使用的首要原則。 
④只查詢索引(index only query)當然where子句中要滿足最左匹配原則 
⑤匹配列前綴(match a column prefix)使用複合索引的第一列的開頭一部分 
⑥複合索引中,一部分匹配精確內容 and 其他部分匹配一個範圍(match one part exactly and match a range on another part) 
⑦列名是索引,那麼column_name is null就會使用索引,比如where column_name is null 
(2)MySQL不使用索引的典型情景 
①like “%query”不使用B-Tree索引,但like “query%”會使用B-Tree索引。 
②數據類型出現隱式轉換的時候也不會使用索引。尤其當列類型是字符串時,一定記得在where條件中把字符串常量值用引號引起來,比如where last_name = ‘1’; 
③使用複合索引時,查詢條件不包含索引的最左邊部分 
④用or 分割的條件,如果其中一個列中沒有索引,則涉及的另一個索引也不會被用到。 
⑤如果MySQL估計使用索引比全表掃描更慢,則不使用索引。

2.優化數據庫對象

2.1選擇合適的存儲引擎
2.2字段選擇合適的數據類型

procedure analyse() 可以對當前應用的表進行分析,對數據表中列的數據類型提出優化建議。

2.3三範式和反三範式
2.4對錶進行水平或者垂直拆分

3.針對存儲引擎的優化

優化特定參數

4.優化MySQL server

4.1MySQL內存管理和優化
4.2InnoDB log機制及優化
4.3調整跟併發相關的MySQL參數

(1)max_connections 
(2)back_log 
(3)table_open_cache 
(4)thread_cache_size 
(5)innodb_lock_wait_timeout

5.磁盤I/O優化

5.1使用磁盤陣列(RAID)
5.2使用Linux虛擬文件卷模擬RAID
5.3符號連接(Symbolic Links)分佈I/O

利用操作系統的符號連接(Symbolic Links)將不同的數據庫、表或索引指向不同的物理磁盤,從而達到分佈磁盤I/O的目的。

5.4禁止操作系統更新文件的atime屬性
5.5用裸設備(Raw Device)存放InnoDB的共享表空間
5.6調整I/O調度算法
5.7RAID卡電池的充放電引起的性能波動
5.8NUMA架構優化

非一致存儲訪問結構(Non-Uniform Memory Access, NUMA)

6.應用優化

6.1使用連接池
6.2減少對MySQL的訪問

①理清應用邏輯,能一次取出的數據不用兩次; 
②使用查詢緩存 
MySQL的查詢緩存(MySQL query cache)是4.1版本之後新增的功能,作用是存儲select的查詢文本和相應結果。如果隨後收到一個相同的查詢,服務器會從查詢緩存中重新得到查詢結果,而不再需要解析和執行查詢。 
查詢緩存適用於更新不頻繁的表,當表更改(包括表結構和數據)後,查詢緩存會被清空。 
③在應用端增加cache層

④負載均衡 
負載均衡(Load Balance)是實際應用中使用非常普遍的一種優化方法,它的機制就是利用某種均衡算法,將固定的負載量分佈到不同的服務器上,以此來減輕單臺服務器的負載,達到優化的目的。負載均衡可以用在系統中的各個層面中,從前臺的 Web 服務器到中間層的應用服務器,最後到數據層的數據庫服務器,都可以使用。 
·利用 MySQL 複製分流查詢和更新操作 
利用 MySQL 的主從複製可以有效地分流更新操作和查詢操作,具體的實現是一個主服務器承擔更新操作,而多臺從服務器承擔查詢操作,主從之間通過複製實現數據的同步。通過複製來分流查詢和更新是減少主數據庫負載的一個常用方法,但是這種辦法也存在一些問題,最主要的問題是當主數據庫上更新頻繁或者網絡出現問題的時候,主從之間的數據可能存在比較大的延遲更新,從而造成查詢結果和主數據庫上有所差異。因此在設計應用的時候需要有所考慮。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章