MySQL優化 - 所需瞭解的基礎知識

    時隔一年半,期間一直想寫但卻以爲沒有實質性的內容可記錄,本文爲 [高性能MySQL] 的學習日誌整理分享(感興趣建議讀原書)。mysql

    優化應貫穿整個產品開發週期中,開發過程當中考慮一些性能問題與影響,總比出問題纔開始重構優化代價要低,因此這些優化知識其實應算需具有的常識。算法

一、MySQL構架的一些知識sql

   1.1 縱觀全貌,邏輯結構以下:數據庫

    關於優化,是一個比較複雜的過程,可能涉及操做系統配置、網絡/磁盤IO、內存、文件系統與應用程序等,知識深刻而且面比較廣,本文只針對MySQL服務器自己的一些可優化點作記錄。緩存

 

1.2 選擇合適的Storage engine很關鍵,MySQL鎖定模型和併發性以下:服務器

加鎖策略 併發 系統開銷 引擎舉例
表級加鎖 最低 最低 MyISAM、Merge、Memory
行級加鎖 NDB Cluster
支持MVCC的行級加鎖 最高 最高 InnoDB

 

 

 

 

部分存儲引擎說明:網絡

MyISAM併發

1. MyISAM 是表級別鎖。
2. 而且不支持數據恢復(服務忽然崩潰應該使用以前進行check)。
3. 不支持事務。
4. 只有索引被緩存在內存中。
5. 數據緊密存儲, 數據讀取比較快速。性能

 

 InnoDB學習

1. 合適大量短事務,使用MVCC機制控制併發鎖定問題,行鎖。
2. 默認隔離級別爲Repeatable Read, 而且使用Next-key locking策略防止幻讀。
3. InnoDB表基於聚簇索引創建,非主鍵索引也包含主鍵列,因此主鍵定義儘可能小一些。

 

 Memory

1. 數據存儲於內存,重啓表結構保留,但數據丟失。
2. 支持哈希索引,可是表級加鎖,只適合低寫入,而且不支持TEXT和BLOB。

注:Temporary table 和 Memory table是兩個不一樣的東西,臨時表只在單個鏈接中可見,鏈接斷開則消失。

 

Archive

1. 只支持insert和select,而且不支持索引。插入時用zlib算法壓縮,佔用空間小。
2. 任何查詢都會致使全表掃描。

 

NDB Cluster:

1. 包含Data Node, Manager Node, SQL Node, 數據冗餘於多個數據節點。
2. 要求高性能的網絡環境,解決複製的延時問題。
3. 該引擎不做爲一個通用的存儲引擎設計,使用前須要深刻了解它是否符合應用場景,它很龐雜。

 

關於存儲引擎的選擇參考因素:

1. 事務, InnoDB處理事務型場景很好。
2. 併發,若是少許插入而且大量讀取,數據可接受崩潰丟失的狀況下,MyISAM效率很好。
3. 備份,是否須要聯機備份。
4. 崩潰恢復,MyISAM在大量數據狀況下崩潰恢復時間很長。
5. 特有特性,若有時候使用到Memory引擎。

對於通常性的應用,InnoDB一般是很常規的引擎選擇。

 

二、關於字符集的關係(雖與優化無關, 但值得一提)

    2.1 建立內置對象

    對於MySQL服務建立的對象,在不指定字符集狀況下:table繼承database,  database繼承server default character。

因此,一般建議在my.cnf中指定數據庫默認的字符集, 以下:

[mysqld]
collation-server=utf8_general_ci
character-set-server=utf8

    同時建議創建數據庫的時候顯式定義數據庫字符集,便於遷移或升級(若是遷移的目標服務器沒定義的話, dump後import就可能字符集就不對應上,致使亂碼等)。

 

    2.2 client / server 通訊使用的字符集

    通訊使用的字符集設置一般包括character_set_client、character_set_connection、character_set_result,它們的關係以下圖:

 

在mysql客戶端的命令下使用show variables like '%character%';  顯示當前鏈接使用的字符集參數。

注:對於mysql客戶端命令,經過配置下面參數以修改上面所說的參數(經過mysql --help --verbose查看默認加載配置文件的路徑):

[mysql]
default-character-set=utf8

對於JDBC,能夠url中加入如useUnicode=yes&characterEncoding=UTF-8來指定特定的字符集,一般建議都使用統一的一種字符集以防止出現未知麻煩。

 

 

三、優化數據類型

優化數據類型一般包含如下幾點說明:

1. 更小的數據類型一般更快,對於使用ORM自動生成的表結構一般不合適(若有些項目使用hibernate自動建立表,通常來講不建議,剛開始省時間,代價後面仍是須要還回來)。

2. 儘可能避免使用NULL, mysql難以優化可以使用空列的查詢,能夠考慮使用0/特殊值/空串等替代,若是計劃對該列進行索引,就儘可能避免設置爲空。。

3. 整數有tinyint,smallint,mediumint,int,bigint,它們分別須要8,16,24,32,64位存儲空間。

4. 主鍵:一般整數做爲主鍵有很是快的索引速度,而且能夠自增加,儘可能避免使用字符串類型做爲標識符,特別注意徹底隨機的字符串(MD5,SHA1()或者UUID()),它們產生的新值會被任意地保存不少的空間範圍內,減慢INSERT(插入的值被隨機放入索引中,致使分頁,隨機磁盤和彙集存儲引擎上的彙集索引碎片)和一些SELECT(由於它分佈在磁盤和內存中的各個地方,致使屢次的讀取)查詢。

Note: 若是對一些絕不關心性能或者數據量極小的應用,自動生成代碼等狀況爲了趕項目就用吧,UUID比MD5,SHA1相比不均勻分佈而且有必定的順序性。

5. 字符串類型(VRAHCR與CHAR), VARCHAR使用可變長字符串, ROW_FORMAT默認爲dynamic,若是使用FIXED則消耗固定長度空間。VARCHAR額外的使用1-2字節存儲長度(小於255則使用1字節)。MySQL會使用固定的內存來存儲varchar的值,如使用varchar(20)和varchar(50)來保存一樣長度的數據,即便它們在磁盤上的消耗是同樣的,可是內存消耗卻相差很大。

 

 

四、關於索引的一些知識

    對於MySQL索引,默認是B-TREE(目前只有這個),因此瞭解一些B-TREE的知識比較有幫助(須要查找專門講解該結構的書籍),有一些能夠參考的點:

1. 若是要對長字符串作索引,索引會變得很大而且很慢,則可模擬哈希索引,取前一部分衝突機率較小的字符串。

2. 多餘索引: 若是對(A, B)列創建組合索引,則沒必要要再單獨對A列創建索引(對於B-Tree而言),因爲最左前綴匹配使得A索引生效,但對B單獨建索引則不是多餘(由於不是最左前綴)。

3. InnoDB在事務提交後纔會給行解鎖,因此儘可能減小對行的鎖定。鎖定超過須要的行會增長競爭並減小併發。InnoDB只有在存儲引擎級過濾不須要的數據才能不鎖定不須要的行,若是是返回給MySQL服務後再使用where過濾的話,已經沒法避免對不須要的行進行鎖定。以下圖則對不須要的第一行進行鎖定 (對於MySQL 5.1 或更新的版本, InnoDB能夠在服務器過濾後進行對不須要的行釋放,舊版本會一直鎖定到事務提交, 建議使用最新的穩定MySQL版本):

 

相關文章
相關標籤/搜索