1. 程式人生 > >MySql優化相關概念的理解筆記

MySql優化相關概念的理解筆記

思維導圖

MySQL架構

在這裡插入圖片描述

查詢執行流程

查詢執行的流程是怎樣的:

  1. 連線
    1.1客戶端發起一條Query請求,監聽客戶端的‘連線管理模組’接收請求
    1.2將請求轉發到‘連線進/執行緒模組’
    1.3呼叫‘使用者模組’來進行授權檢查
    1.4通過檢查後,‘連線進/執行緒模組’從‘執行緒連線池’中取出空閒的被快取的連線執行緒和客戶端請求對接,如果失敗則建立一個新的連線請求。
  2. 處理
    2.1先查詢快取,檢查Query語句是否完全匹配,
    2.2查詢快取失敗則轉交給‘命令解析器’
    2.3再轉交給對應的模組處理
    2.4如果是SELECT查詢還會經由‘查詢優化器’做大量的優化,生成執行計劃
    2.5模組收到請求後,通過‘訪問控制模組’檢查所連線的使用者是否有訪問目標表和目標欄位的許可權
    2.6有則呼叫‘表管理模組’,先是檢視table cache中是否存在,有則直接對應的表和獲取鎖,否則重新開啟表文件
    2.8根據表的meta資料,獲取表的儲存引擎型別等資訊,通過介面呼叫對應的儲存引擎處理
    2.9上述過程中產生資料變化的時候,若開啟日誌功能,則會記錄到相應二進位制日誌檔案中
  3. 結果
    3.1Query請求完成後,將結果集返回給‘連線進/執行緒模組’
    3.2返回的也可以是相應的狀態標識,如成功或失敗等
    3.3‘連線進/執行緒模組’進行後續的清理工作,並繼續等待請求或斷開與客戶端的連線

什麼是優化

  • 合理安排資源、調整系統引數使MySQL執行更快、更節省資源。
  • 優化是多方面的,包括查詢、表設計、伺服器等。
  • 原則:減少系統瓶頸,減少資源佔用,增加系統的反應速度。

查詢優化

在優化MySQL時,通常需要庫進行分析。常見的分析手段有慢查詢日誌EXPLAIN 分析查詢,通過定位分析效能的瓶頸,才能更好的優化資料庫系統的效能。

慢查詢日誌

慢查詢日誌開啟
在配置檔案my.cnf或my.ini中在[mysqld]一行下面加入兩個配置引數
log-slow-queries=/data/mysqldata/slow-query.log
long_query_time=5
注:log-slow-queries引數為慢查詢日誌存放的位置,一般這個目錄要有mysql的執行帳號的可寫許可權,一般都將這個目錄設定為mysql的資料存放目錄;
long_query_time=5中的5表示查詢超過五秒才記錄;
還可以在my.cnf或者my.ini中新增log-queries-not-using-indexes引數,表示記錄下沒有使用索引的查詢。
慢查詢分析


我們可以通過開啟log檔案檢視得知哪些SQL執行效率低下
從日誌中,可以發現查詢時間超過5 秒的SQL,而小於5秒的沒有出現在此日誌中。
如果慢查詢日誌中記錄內容很多,可以使用mysqldumpslow工具(MySQL客戶端安裝自帶)來對慢查詢日誌進行分類彙總。mysqldumpslow對日誌檔案進行了分類彙總,顯示彙總後摘要結果。
進入log的存放目錄,執行
[[email protected]_data]#mysqldumpslow slow-query.log
Reading mysql slow query log from slow-query.log
Count: 2 Time=11.00s (22s) Lock=0.00s (0s) Rows=1.0 (2), root[root]@mysql
select count(N) from t_user;

mysqldumpslow命令
/path/mysqldumpslow -s c -t 10 /database/mysql/slow-query.log
這會輸出記錄次數最多的10條SQL語句,其中:

-s, 是表示按照何種方式排序,c、t、l、r分別是按照記錄次數、時間、查詢時間、返回的記錄數來排序,ac、at、al、ar,表示相應的倒敘
-t, 是top n的意思,即為返回前面多少條的資料;
-g, 後邊可以寫一個正則匹配模式,大小寫不敏感的;

例如:
/path/mysqldumpslow -s r -t 10 /database/mysql/slow-log
得到返回記錄集最多的10個查詢。
/path/mysqldumpslow -s t -t 10 -g “left join” /database/mysql/slow-log
得到按照時間排序的前10條裡面含有左連線的查詢語句。

使用mysqldumpslow命令可以非常明確的得到各種我們需要的查詢語句,對MySQL查詢語句的監控、分析、優化是MySQL優化非常重要的一步。開啟慢查詢日誌後,由於日誌記錄操作,在一定程度上會佔用CPU資源影響mysql的效能,但是可以階段性開啟來定位效能瓶頸。

EXPLAIN

在MySQL中可以使用EXPLAIN檢視SQL執行計劃,用法:EXPLAIN SELECT * FROM products
5.2.1.id
SELECT識別符。這是SELECT查詢序列號。這個不重要。
5.2.2.select_type
表示SELECT語句的型別。
例如:
1、SIMPLE
表示簡單查詢,其中不包含連線查詢和子查詢。
2、PRIMARY
表示主查詢,或者是最外面的查詢語句。
3、UNION
表示連線查詢的第2個或後面的查詢語句。
5.2.3.table
表示查詢的表。
5.2.4.type
表示表的連線型別。
以下的連線型別的順序是從最佳型別到最差型別:
1、system
表僅有一行,這是const型別的特列,平時不會出現,這個也可以忽略不計。
2、const
資料表最多隻有一個匹配行,因為只匹配一行資料,所以很快,常用於
3、eq_ref
mysql手冊是這樣說的:“對於每個來自於前面的表的行組合,從該表中讀取一行。這可能是最好的聯接型別,除了const型別。它用在一個索引的所有部分被聯接使用並且索引是UNIQUE或PRIMARY KEY”。eq_ref可以用於使用=比較帶索引的列。
4、ref
查詢條件索引既不是UNIQUE也不是PRIMARY KEY的情況。ref可用於=或<或>操作符的帶索引的列。
5、ref_or_null
該聯接型別如同ref,但是添加了MySQL可以專門搜尋包含NULL值的行。在解決子查詢中經常使用該聯接型別的優化。
上面這五種情況都是很理想的索引使用情況。
6、index_merge
該聯接型別表示使用了索引合併優化方法。在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。
7、unique_subquery
該型別替換了下面形式的IN子查詢的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一個索引查詢函式,可以完全替換子查詢,效率更高。
8、index_subquery
該聯接型別類似於unique_subquery。可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
9、range
只檢索給定範圍的行,使用一個索引來選擇行。
10、index
該聯接型別與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引檔案通常比資料檔案小。
11、ALL
對於每個來自於先前的表的行組合,進行完整的表掃描。(效能最差)
5.2.5.possible_keys
指出MySQL能使用哪個索引在該表中找到行。
如果該列為NULL,說明沒有使用索引,可以對該列建立索引來提高效能。
5.2.6.key
顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。
5.2.7.key_len
顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度為NULL。
注意:key_len是確定了MySQL將實際使用的索引長度。
5.2.8.ref
顯示使用哪個列或常數與key一起從表中選擇行。
5.2.9.rows
顯示MySQL認為它執行查詢時必須檢查的行數。
5.2.10.Extra
該列包含MySQL解決查詢的詳細資訊
Distinct:MySQL發現第1個匹配行後,停止為當前的行組合搜尋更多的行。
Not exists:MySQL能夠對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行後,不再為前面的的行組合在該表內檢查更多的行。
range checked for each record (index map: #):MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用。
Using filesort:MySQL需要額外的一次傳遞,以找出如何按排序順序檢索行。
Using index:從只使用索引樹中的資訊而不需要進一步搜尋讀取實際的行來檢索表中的列資訊。
Using temporary:為了解決查詢,MySQL需要建立一個臨時表來容納結果。
Using where:WHERE 子句用於限制哪一個行匹配下一個表或傳送到客戶。
Using sort_union(…), Using union(…), Using intersect(…):這些函式說明如何為index_merge聯接型別合併索引掃描。
Using index for group-by:類似於訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,可以用來查 詢GROUP BY或DISTINCT查詢的所有列,而不要額外搜尋硬碟訪問實際的表。

索引使用

6.1.1.MySQL索引
6.1.1.1.B-Tree索引
一般來說,MySQL中的B-Tree索引的物理檔案大多都是以二叉樹的結構來儲存的,也就是所有實際需要的資料都存放於樹的葉子節點,而且到任何一個葉子節點的最短路徑的長度都是完全相同的。
6.1.1.2.R-Tree索引
RTREE在mysql很少使用,支援該型別的儲存引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種。相對於BTREE,RTREE的優勢在於範圍查詢.
6.1.1.3.Hash索引
Hash索引在MySQL中使用的並不是很多,目前主要是Memory儲存引擎使用,而且在Memory儲存引擎中將Hash索引作為預設的索引型別。所謂Hash索引,實際上就是通過一定的Hash演算法,將需要索引的鍵值進行Hash運算,然後將得到的Hash值存入一個Hash表中。然後每次需要檢索的時候,都會將檢索條件進行相同演算法的Hash運算,然後再和Hash表中的Hash值進行比較並得出相應的資訊。
Hash索引僅僅只能滿足“=”,“IN”和“<=>”查詢,不能使用範圍查詢;
Hash索引無法被利用來避免資料的排序操作;
Hash索引不能利用部分索引鍵查詢;
Hash索引在任何時候都不能避免表掃面;
Hash索引遇到大量Hash值相等的情況後效能並不一定就會比B-Tree索引高;
6.1.1.4.Full-text索引
Full-text索引也就是我們常說的全文索引,目前在MySQL中僅有MyISAM儲存引擎支援,而且也並不是所有的資料型別都支援全文索引。目前來說,僅有CHAR,VARCHAR和TEXT這三種資料型別的列可以建Full-text索引。
6.1.2.建立索引
是否需要建立索引,幾點原則:

  • 較頻繁的作為查詢條件的欄位應該建立索引;
  • 唯一性太差的欄位不適合單獨建立索引,即使頻繁作為查詢條件;
  • 更新非常頻繁的欄位不適合建立索引;
  • 不會出現在WHERE子句中的欄位不該建立索引;
    索引能夠極大的提高資料檢索效率,也能夠改善排序分組操作的效能,但是我們不能忽略的一個問題就是索引是完全獨立於基礎資料之外的一部分資料,更新資料會帶來的IO量和調整索引所致的計算量的資源消耗。
    6.1.3.使用索引
    6.1.3.1.使用聯合索引的查詢
    MySQL可以為多個欄位建立索引,一個索引可以包括16個欄位。對於聯合索引,只有查詢條件中使用了這些欄位中第一個欄位時,索引才會生效。
    6.1.3.2.使用OR關鍵字的查詢
    查詢語句的查詢條件中只有OR關鍵字,且OR前後的兩個條件中的列都是索引時,索引才會生效,否則,索引不生效。

儲存優化

儲存資料時,影響儲存速度的主要是索引、唯一性校驗、一次儲存的資料條數等。

儲存資料的優化,不同的儲存引擎優化手段不一樣,在MySQL中常用的儲存引擎有,MyISAM和InnoDB,兩者的區別:

7.1.儲存引擎介紹
7.1.1.MyISAM儲存引擎
MyISAM儲存引擎是一種非事務性的引擎,提供高速儲存和檢索,以及全文搜尋能力,適合資料倉庫等查詢頻繁的應用。

每一個表都被存放為三個以表名命名的物理檔案。有存放表結構定義資訊的.frm檔案,還有存放了表的資料.MYD檔案和存放索引資料的.MYI檔案。

7.1.2.Innodb 儲存引擎
Innodb 儲存引擎是事務安全的, 因此如果需要一個事務安全的儲存引擎,建議使用它。如果你的資料執行大量的INSERT或UPDATE,出於效能方面的考慮應該使用InnoDB表。

InnoDB 給 MySQL 提供了具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。InnoDB 提供了行鎖(locking on row level),提供與 Oracle 型別一致的不加鎖讀取(non-locking read in SELECTs)。這些特性均提高了多使用者併發操作的效能表現。

在InnoDB表中不需要擴大鎖定(lock escalation),因為 InnoDB 的列鎖定(row level locks)適宜非常小的空間。InnoDB 是 MySQL 上提供外來鍵約束(FOREIGN KEY constraints)的表引擎。

InnoDB 的設計目標是處理大容量資料庫系統,它的 CPU 利用率是其它基於磁碟的關係資料庫引擎所不能比的。在技術上,InnoDB 是一套放在 MySQL 後臺的完整資料庫系統,InnoDB 在主記憶體中建立其專用的緩衝池用於高速緩衝資料和索引。

InnoDB 把資料和索引存放在表空間裡,可能包含多個檔案,這與MyISAM不一樣。InnoDB 表的大小隻受限於作業系統的檔案大小,一般為 2 GB。InnoDB所有的表都儲存在同一個資料檔案 ibdata1 中(也可能是多個檔案,或者是獨立的表空間檔案),相對來說比較不好備份。備份的方案可以是拷貝資料檔案、備份 binlog,或者用 mysqldump。

7.2.MyISAM和Innodb的區別
InnoDB和MyISAM是許多人在使用MySQL時最常用的兩個表型別,這兩個表型別各有優劣,視具體應用而定。基本的差別為:MyISAM型別不支援事務處理等高階處理,而InnoDB型別支援。MyISAM型別的表強調的是效能,其執行數度比InnoDB型別更快,但是不提供事務支援,而InnoDB提供事務支援已經外部鍵等高階資料庫功能。

7.2.1.具體實現的差別:

  • MyISAM是非事務安全型的,而InnoDB是事務安全型的。
  • MyISAM鎖的粒度是表級,而InnoDB支援行級鎖定。
  • MyISAM支援全文型別索引,而InnoDB不支援全文索引。
  • MyISAM相對簡單,所以在效率上要優於InnoDB,小型應用可以考慮使用MyISAM。
  • MyISAM表是儲存成檔案的形式,在跨平臺的資料轉移中使用MyISAM儲存會省去不少的麻煩。
  • InnoDB表比MyISAM表更安全,可以在保證資料不會丟失的情況下,切換非事務表到事務表(alter table tablename type=innodb)。

7.2.2.應用場景

  • MyISAM管理非事務表。它提供高速儲存和檢索,以及全文搜尋能力。如果應用中需要執行大量的SELECT查詢,那麼MyISAM是更好的選擇。
  • InnoDB用於事務處理應用程式,具有眾多特性,包括ACID事務支援。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多使用者併發操作的效能。
    7.3.MyISAM儲存優化
    7.3.1.禁用索引
    對於非空表,插入記錄時,MySQL會根據表的索引對插入的記錄建立索引。如果插入大量資料,建立索引會降低插入資料速度。
    為了解決這個問題,可以在批量插入資料之前禁用索引,資料插入完成後再開啟索引。
    禁用索引的語句:
    ALTER TABLE table_name DISABLE KEYS
    開啟索引語句:
    ALTER TABLE table_name ENABLE KEYS
    對於空表批量插入資料,則不需要進行操作,因為MyISAM引擎的表是在匯入資料後才建立索引。
    7.3.2.禁用唯一性檢查
    唯一性校驗會降低插入記錄的速度,可以在插入記錄之前禁用唯一性檢查,插入資料完成後再開啟。
    禁用唯一性檢查的語句:SET UNIQUE_CHECKS = 0;
    開啟唯一性檢查的語句:SET UNIQUE_CHECKS = 1;
    7.3.3.批量插入資料
    插入資料時,可以使用一條INSERT語句插入一條資料,也可以插入多條資料。
    7.3.4.使用LOAD DATA INFILE
    當需要批量匯入資料時,使用LOAD DATA INFILE語句比INSERT語句插入速度快很多。
    7.4.InnoDB
    7.4.1.禁用唯一性檢查
    用法和MyISAM一樣。
    7.4.2.禁用外來鍵檢查
    插入資料之前執行禁止對外來鍵的檢查,資料插入完成後再恢復,可以提供插入速度。
    禁用:SET foreign_key_checks = 0;
    開啟:SET foreign_key_checks = 1;
    7.4.3.禁止自動提交
    插入資料之前執行禁止事務的自動提交,資料插入完成後再恢復,可以提高插入速度。
    禁用:SET autocommit = 0;
    開啟:SET autocommit = 1;

資料庫結構優化

8.1.優化表結構

  • 儘量將表字段定義為NOT NULL約束,這時由於在MySQL中含有空值的列很難進行查詢優化,NULL值會使索引以及索引的統計資訊變得很複雜。
  • 對於只包含特定型別的欄位,可以使用enum、set 等符合資料型別。
  • 數值型欄位的比較比字串的比較效率高得多,欄位型別儘量使用最小、最簡單的資料型別。例如P地址可以使用int型別。
  • 儘量使用TINYINT、SMALLINT、MEDIUM_INT作為整數型別而非INT,如果非負則加上UNSIGNED
  • VARCHAR的長度只分配真正需要的空間
  • 儘量使用TIMESTAMP而非DATETIME,
  • 單表不要有太多欄位,建議在20以內
  • 合理的加入冗餘欄位可以提高查詢速度。

8.2.表拆分

8.2.1.垂直拆分
垂直拆分按照欄位進行拆分,其實就是把組成一行的多個列分開放到不同的表中,這些表具有不同的結構,拆分後的表具有更少的列。例如使用者表中的一些欄位可能經常訪問,可以把這些欄位放進一張表裡。另外一些不經常使用的資訊就可以放進另外一張表裡。

插入的時候使用事務,也可以保證兩表的資料一致。缺點也很明顯,由於拆分出來的兩張表存在一對一的關係,需要使用冗餘欄位,而且需要join操作,我們在使用的時候可以分別取兩次,這樣的來說既可以避免join操作,又可以提高效率。

8.2.2.水平拆分
水平拆分按照行進行拆分,常見的就是分庫分表。以使用者表為例,可以取使用者ID,然後對ID取10的餘數,將使用者均勻的分配進這 0-9這10個表中。查詢的時候也按照這種規則,又快又方便。

有些表業務關聯比較強,那麼可以使用按時間劃分的。例如每天的資料量很大,需要每天新建一張表。這種業務型別就是需要高速插入,但是對於查詢的效率不太關心。表越大,插入資料所需要索引維護的時間也就越長。
8.3.分割槽
使用分割槽是大資料處理後的產物。比如系統使用者的註冊推廣等等,會產生海量的日誌,當然也可以按照時間水平拆分,建立多張表。但在實際操作中,容易發生忘記切換表導致資料錯誤。
分割槽適用於例如日誌記錄,查詢少。一般用於後臺的資料報表分析。對於這些資料彙總需求,需要很多日誌表去做資料聚合,我們能夠容忍1s到2s的延遲,只要資料準確能夠滿足需求就可以。
MySQL主要支援4種模式的分割槽:range分割槽、list預定義列表分割槽,hash 分割槽,key鍵值分割槽。
8.4.讀寫分離
大型網站會有大量的併發訪問,如果還是傳統的資料結構,或者只是單單靠一臺伺服器扛,如此多的資料庫連線操作,資料庫必然會崩潰,資料丟失的話,後果更是不堪設想。這時候,我們需要考慮如何減少資料庫的聯接。
我們發現一般情況對資料庫而言都是“讀多寫少”,也就說對資料庫讀取資料的壓力比較大,這樣分析可以採用資料庫叢集的方案。其中一個是主庫,負責寫入資料,我們稱為寫庫;其它都是從庫,負責讀取資料,我們稱為讀庫。這樣可以緩解一臺伺服器的訪問壓力
8.5.資料庫叢集
如果訪問量非常大,雖然使用讀寫分離能夠緩解壓力,但是一旦寫操作一臺伺服器都不能承受了,這個時候我們就需要考慮使用多臺伺服器實現寫操作。
例如可以使用MyCat搭建MySql叢集,對ID求3的餘數,這樣可以把資料分別存放到3臺不同的伺服器上,由MyCat負責維護叢集節點的使用。

硬體優化

是伺服器的硬體效能直接決定著MySQL資料庫的效能,硬體的效能瓶頸,直接決定MySQL資料庫的執行速度和效率。

可以從以下幾個方面考慮:
1、配置較大的記憶體。足夠大的記憶體,是提高MySQL資料庫效能的方法之一。記憶體的IO比硬碟快的多,可以增加系統的緩衝區容量,使資料在記憶體停留的時間更長,以減少磁碟的IO。

2、磁碟I/O相關

  • 使用SSD或者PCIe SSD裝置,至少獲得數百倍甚至萬倍的IOPS提升;
  • 購置陣列卡同時配備CACHE及BBU模組,可明顯提升IOPS
  • 儘可能選用RAID-10,而非RAID-5
  • 使用機械盤的話,儘可能選擇高轉速的,例如選用15000RPM,而不是7200RPM的盤
    3、配置CPU相關
       在伺服器的BIOS設定中,可調整下面的幾個配置:
  • 選擇Performance Per Watt Optimized(DAPC)模式,發揮CPU最大效能;
  • 關閉C1E和C States等選項,提升CPU效率;
  • Memory Frequency(記憶體頻率)選擇Maximum Performance;

MySQL快取

為了提高查詢速度,我們可以通過不同的方式去快取我們的結果從而提高響應效率。當我們的資料庫打開了Query Cache(簡稱QC)功能後,資料庫在執行SELECT語句時,會將其結果放到QC中,當下一次處理同樣的SELECT請求時,資料庫就會從QC取得結果,而不需要去資料表中查詢。如果快取命中率非常高的話,有測試表明在極端情況下可以提高效率238%。
但一個快取機制是否有效,效果如何,卻是一個需要好好思考的問題。Query Cache有如下規則,如果資料表被更改,那麼和這個資料表相關的全部Cache全部都會無效,並刪除之。這裡“資料表更改”包括: INSERT, UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP TABLE, or DROP DATABASE等。
舉個例子,如果資料表item訪問頻繁,那麼意味著它的很多資料會被QC快取起來,但是每一次item資料表的更新,無論更新是不是影響到了cache 的資料,都會將全部和item表相關的cache清除。如果你的資料表更新頻繁的話,那麼Query Cache將會成為系統的負擔。有實驗表明,糟糕時,QC會降低系統13%的處理能力。
10.1.1.全域性快取
資料庫屬於IO密集型的應用程式,其主職責就是資料的管理及儲存工作。而我們知道,從記憶體中讀取一個數據庫的時間是微秒級別,而從一塊普通硬碟上讀取一個 IO是在毫秒級別,二者相差3個數量級。所以,要優化資料庫,首先第一步需要優化的就是IO,儘可能將磁碟IO轉化為記憶體IO,也就是使用快取
啟動MySQL時就要分配並且總是存在的全域性快取,可以在MySQL的my.conf或者my.ini檔案的[mysqld]組中配置。
目前有:
key_buffer_size(預設值:402653184,即384M)、
innodb_buffer_pool_size(預設值:134217728即:128M)、innodb_additional_mem_pool_size(預設值:8388608即:8M)、innodb_log_buffer_size(預設值:8388608即:8M)、query_cache_size(預設值:33554432即:32M)等五個。總共:560M.
10.1.1.1.key_buffer_size
key_buffer_size是用於索引塊的緩衝區大小,增加它可得到更好處理的索引(對所有讀和多重寫),對MyISAM表效能影響最大的一個引數。如果你使它太大,系統將開始換頁並且真的變慢了。
嚴格說是它決定了資料庫索引處理的速度,尤其是索引讀的速度。對於記憶體在4GB左右的伺服器該引數可設定為256M或384M.
10.1.1.2.innodb_buffer_pool_size
innodb_buffer_pool_size:主要針對InnoDB表效能影響最大的一個引數。功能與Key_buffer_size一樣。InnoDB佔用的記憶體,除innodb_buffer_pool_size用於儲存頁面快取資料外,另外正常情況下還有大約8%的開銷,主要用在每個快取頁幀的描述、adaptive hash等資料結構,如果不是安全關閉,啟動時還要恢復的話,還要另開大約12%的記憶體用於恢復,兩者相加就有差不多21%的開銷。
10.1.1.3.innodb_additional_mem_pool_size
innodb_additional_mem_pool_size 設定了InnoDB儲存引擎用來存放資料字典資訊以及一些內部資料結構的記憶體空間大小,所以當我們一個MySQL Instance中的資料庫物件非常多的時候,是需要適當調整該引數的大小以確保所有資料都能存放在記憶體中提高訪問效率的。
10.1.1.4.innodb_log_buffer_size
innodb_log_buffer_size這是InnoDB儲存引擎的事務日誌所使用的緩衝區。類似於Binlog Buffer
InnoDB在寫事務日誌的時候,為了提高效能,也是先將資訊寫入Innofb Log Buffer中,當滿足innodb_flush_log_trx_commit引數所設定的相應條件(或者日誌緩衝區寫滿)之後,才會將日誌寫到檔案 (或者同步到磁碟)中。可以通過innodb_log_buffer_size 引數設定其可以使用的最大記憶體空間。
InnoDB 將日誌寫入日誌磁碟檔案前的緩衝大小。理想值為 1M 至 8M。大的日誌緩衝允許事務執行時不需要將日誌儲存入磁碟而只到事務被提交(commit)。 因此,如果有大的事務處理,設定大的日誌緩衝可以減少磁碟I/O。 這個引數實際上還和另外的flush引數相關。一般來說不建議超過32MB
10.1.1.5.query_cache_size
query_cache_size: 主要用來快取MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。
當我們打開了 Query Cache功能,MySQL在接受到一條select語句的請求後,如果該語句滿足Query Cache的要求,MySQL會直接根據預先設定好的HASH演算法將接受到的select語句以字串方式進行hash,然後到Query Cache中直接查詢是否已經快取。如果已經在快取中,該select請求就會直接將資料返回,從而省略了後面所有的步驟(如SQL語句的解析,優化器優化以及向儲存引擎請求資料等),極大的提高效能。
當然,Query Cache也有一個致命的缺陷,那就是當某個表的資料有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的快取資料失效。所以,當我們的資料變化非常頻繁的情況下,使用Query Cache可能會得不償失
10.1.2.區域性快取
除了全域性緩衝,MySql還會為每個連線發放連線緩衝。個連線到MySQL伺服器的執行緒都需要有自己的緩衝。大概需要立刻分配256K,甚至線上程空閒時,它們使用預設的執行緒堆疊,網路快取等。事務開始之後,則需要增加更多的空間。執行較小的查詢可能僅給指定的執行緒增加少量的記憶體消耗,然而如果對資料表做複雜的操作例如掃描、排序或者需要臨時表,則需分配大約read_buffer_size,
sort_buffer_size,read_rnd_buffer_size,tmp_table_size 大小的記憶體空間. 不過它們只是在需要的時候才分配,並且在那些操作做完之後就釋放了。
10.1.2.1.read_buffer_size
read_buffer_size是MySql讀入緩衝區大小。對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會為它分配一段記憶體緩衝區。read_buffer_size變數控制這一緩衝區的大小。如果對錶的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變數值以及記憶體緩衝區大小提高其效能.
10.1.2.2.sort_buffer_size
sort_buffer_size是MySql執行排序使用的緩衝大小。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試增加sort_buffer_size變數的大小
10.1.2.3.read_rnd_buffer_size
read_rnd_buffer_size 是MySql的隨機讀緩衝區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀快取區。進行排序查詢時,MySql會首先掃描一遍該緩衝,以避免磁碟搜尋,提高查詢速度,如果需要排序大量資料,可適當調高該值。但MySql會為每個客戶連線發放該緩衝空間,所以應儘量適當設定該值,以避免記憶體開銷過大。
10.1.2.4.tmp_table_size
tmp_table_size是MySql的heap (堆積)表緩衝大小。所有聯合在一個DML指令內完成,並且大多數聯合甚至可以不用臨時表即可以完成。大多數臨時表是基於記憶體的(HEAP)表。具有大的記錄長度的臨時表 (所有列的長度的和)或包含BLOB列的表儲存在硬碟上。
如果某個內部heap(堆積)表大小超過tmp_table_size,MySQL可以根據需要自動將記憶體中的heap表改為基於硬碟的MyISAM表。還可以通過設定tmp_table_size選項來增加臨時表的大小。也就是說,如果調高該值,MySql同時將增加heap表的大小,可達到提高聯接查詢速度的效果。
10.1.2.5.record_buffer:
record_buffer每個進行一個順序掃描的執行緒為其掃描的每張表分配這個大小的一個緩衝區。如果你做很多順序掃描,你可能想要增加該值。
10.1.3.其它快取
10.1.3.1.table_cache
TABLE_CACHE(5.1.3及以後版本又名TABLE_OPEN_CACHE),table_cache指定表快取記憶體的大小。每當MySQL訪問一個表時,如果在表緩衝區中還有空間,該表就被開啟並放入其中,這樣可以更快地訪問表內容。
不能盲目地把table_cache設定成很大的值。如果設定得太高,可能會造成檔案描述符不足,從而造成效能不穩定或者連線失敗。
4.2.3.2 thread_cache_size (伺服器執行緒快取)
預設的thread_cache_size=8,,這個值表示可以重新利用儲存在快取中執行緒的數量,當斷開連線時如果快取中還有空間,那麼客戶端的執行緒將被放到快取中,如果執行緒重新被請求,那麼請求將從快取中讀取,如果快取中是空的或者是新的請求,那麼這個執行緒將被重新建立,如果有很多新的執行緒,
增加這個值可以改善系統性能.通過比較 Connections 和 Threads_created 狀態的變數,可以看到這個變數的作用。
11.MySQL伺服器引數
通過優化MySQL的引數可以提高資源利用率,從而達到提高MySQL伺服器效能的目的。MySQL的配置引數都在my.conf或者my.ini檔案的[mysqld]組中,常用的引數如下:
11.1.back_log
back_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆疊中(每個連線256kb,佔用:125M)。也就是說,如果MySql的連線資料達到max_connections時,新來的請求將會被存在堆疊中,以等待某一連線釋放資源,該堆疊的數量即back_log,如果等待連線的數量超過back_log,將不被授予連線資源。
11.2.wait_timeout
當MySQL連線閒置超過一定時間後將會被強行關閉。MySQL預設的wait-timeout值為8個小時。
設定這個值是非常有意義的,比如你的網站有大量的MySQL連結請求(每個MySQL連線都是要記憶體資源開銷的),由於你的程式的原因有大量的連線請求空閒啥事也不幹,白白佔用記憶體資源,或者導致MySQL超過最大連線數從來無法新建連線導致“Too many connections”的錯誤。在設定之前你可以檢視一下你的MYSQL的狀態(可用showprocesslist),如果經常發現MYSQL中有大量的Sleep程序,則需要 修改wait-timeout值了。
11.3.max_connections
max_connections是指MySql的最大連線數,如果伺服器的併發連線請求量比較大,建議調高此值,以增加並行連線數量,當然這建立在機器能支撐的情況下,因為如果連線數越多,介於MySql會為每個連線提供連線緩衝區,就會開銷越多的記憶體,所以要適當調整該值,不能盲目提高設值。
MySQL伺服器允許的最大連線數16384
11.4.max_user_connections
max_user_connections是指每個資料庫使用者的最大連線針對某一個賬號的所有客戶端並行連線到MYSQL服務的最大並行連線數。簡單說是指同一個賬號能夠同時連線到mysql服務的最大連線數。設定為0表示不限制。
11.5.thread_concurrency
thread_concurrency的值的正確與否, 對mysql的效能影響很大, 在多個cpu(或多核)的情況下,錯誤設定了thread_concurrency的值, 會導致mysql不能充分利用多cpu(或多核), 出現同一時刻只能一個cpu(或核)在工作的情況。thread_concurrency應設為CPU核數的2倍。
11.6.skip-name-resolve
skip-name-resolve:禁止MySQL對外部連線進行DNS解析,使用這一選項可以消除MySQL進行DNS解析的時間。但需要注意,如果開啟該選項,則所有遠端主機連線授權都要使用IP地址方式,否則MySQL將無法正常處理連線請求!
11.7.default-storage-engine
default-storage-engine= InnoDB(設定InnoDB型別,另外還可以設定MyISAM型別)設定建立資料庫及表預設儲存型別