MySQL的使用優化主要從優化庫表結構、使用合適的索引、優化查詢等方面考慮。mysql
在MySQL中表示字符串的類型有多種,其中常見的有Char和VarChar,BLOB和TEXT以及能夠實現某些優化的ENUM。咱們要認識到不一樣的數據類型在存儲和使用的區別,而後合理的使用就能實現優化。sql
關於MySQL中數據類型的介紹,能夠參看個人另外一篇博文: MySQL的常見操做數據庫
Char和VarChar緩存
Char是定長類型,MySQL會根據定義的字符串的長度分配足夠的空間,而且MySQL在存儲CHAR值的時候會刪除末尾全部的空格。對於常常變動的數據,通常採用CHAR來進行存儲,由於CHAR類型在變化的時候不容易產生碎片。服務器
VARCHAR是變長類型,它比CHAR更加節省空間,可是VARCHAR在數據變化的時候容易產生碎片,因此通常用於做爲不常常變化的數據的數據類型。VARCHAR須要多使用一個或者兩個額外字節來記錄字符串的長度,若是列的最大長度小於等於255字節就用一個額外的字節來存儲長度,不然使用兩個字節。例如VARCHAR(10)的列須要11個字節的存儲空間,VARCHAR(1000)的列須要1002個字節。併發
注意,在5.0或者更高的版本中,MySQL在存儲或者檢索VARCHAR數據類型時保留末尾空格,可是在4.1或者更老的版本中,MySQL在存儲或者檢索VARCHAR數據類型時和CHAR同樣都是刪除末尾的空格app
BLOB和TEXT函數
BLOB即SMALLBLOB,TEXT即SMALLTEXT。BLOB和TEXT都是爲了存儲很大的數據而設計的字符串數據類型,分別採用二進制和字符串的方式來存儲。性能
使用ENUM來代替字符串類型測試
MySQL在存儲枚舉的時候很是的緊湊,會根據列表值的數量壓縮到一個或者兩個字節中。MySQL在內部會將每一個值在列表中的位置保存爲整數,而且在表的.frm文件中保存"數字-字符串"映射關係的"查找表"。
例如:create table enum_test(e enum('apple','banana','pear'));insert into enum_test(e) values('apple'),('banana'),('pear');
而後咱們所插入的數據在表中實際上是存儲爲整數的。
MySQL能夠爲整數類型指定寬度,如INT(1),INT(20),可是這對大多數應用是沒有意義的。MySQL所指定的整數類型的寬度只是用於設置一些MySQL客戶端用於顯示字符的個數,對於存儲和計算而言,INT(1)和INT(20)不會限制值的合法範圍,這兩種類型都是相同的。
DateTime和TimeStamp
DATETIME和TIMESTAMP是兩種日期類型,兩種類型在MySQL中存儲數據的格式徹底相同(都是yyyy-MM-dd HH:mm:ss),可是二者也有不一樣之處。
DATETIME能保存大範圍的值,從1001年到9999年,精度爲秒。MySQL採用8個字節來存儲DATETIME數據類型所包含的值。默認狀況下,MySQL以一種可排序的、無歧義的格式顯示DATETIME的值。
TIMESTAMP保存了從1970年1月1日午夜(格林尼治標準時間)以來的秒數,它和UNIX的時間戳相同。TIMESTAMP僅僅使用4個字節的存儲空間,因此它能表示的時間範圍也比DATETIME小,只能表示從1970年到2038年。TIMESTAMP也有DATETIME沒有的特殊屬性,默認狀況下,若是插入時沒有指定第一個TIMESTAMP列的值,MySQL則設置該列的值爲當前時間。
索引優化是一個很大的方面,這裏只是簡單的介紹一些基本使用,事後會推出關於索引優化與設計的專題。
在MySQL中,索引是在存儲引擎層而不是服務器層實現的。Mysql中索引結構有:B-Tree索引、哈希索引、空間數據索引(R-Tree索引)、全文索引等索引結構,不一樣的存儲引擎對於上述索引結構的實現不一樣,並且也不是全部的存儲引擎都有這5種索引結構類型。
索引類型:
MySQL中的索引類型主要有5種:
ALTER TABLE article ADD INDEX index_title_name ON title(100);
、CREATE INDEX index_name ON table(column(100))
,或者直接在建立表的時候定義索引index index_title_name(title(100))
ALTER TABLE article ADD UNIQU index_title_name ON title(100);
、CREATE UNIQUE INDEX index_name ON table(column(100))
或者直接在建立表的時候定義索引UNIQUE index_title_name(title(100))
ALTER TABLE article ADD FULLTEXT index_content(content)
、CREATE FULLTEXT INDEX index_content ON article(content)
和FULLTEXT (content)
。索引方法:
可使用B樹索引的查詢:
使用B樹索引的限制
Hash索引的特色:
Hash索引是基於Hash表實現的,只有查詢條件精確匹配Hash索引中的全部列時,才能使用Hash索引,Hash索引只適用於等值查詢不適合模糊查詢和範圍查詢。
對於Hash索引中的全部列,存儲引擎都會爲該列的每一行計算一個Hash碼,Hash索引中存儲的就是Hash碼。
使用Hash索引的限制:
B樹索引與Hash索引在不少地方是不一樣的。B樹索引除了能加快數據的查找速度以外還能夠作到排序和分組,B樹索引的葉子節點存儲了索引關鍵字的值,能夠直接經過索引查找關鍵字的信息從而避免了訪問數據行。可是Hash索引的葉子節點中存儲的是關鍵字信息的Hash碼,咱們須要將查詢信息轉化成Hash在表中找到對應的數據行才能查找到數據的信息。所以Hash索引不能做爲覆蓋索引來使用。
覆蓋索引:
若是一個索引包含全部須要查詢的字段的值(where語句的參數、order by的參數、group by的參數),那麼咱們一般稱這個索引爲覆蓋索引。對於Memory存儲引擎不能使用覆蓋索引,查詢過程當中若是包含了太多的列(如select *)也不適合使用覆蓋索引。 使用覆蓋索引也有不少的優勢。
InnoDB做爲MySQL最爲著名的存儲引擎,這裏要作特別的介紹。InnoDB中存儲引擎支持B+樹索引、全文索引和哈希索引。InnoDB存儲引擎支持的哈希引擎是自適應的,InnoDB存儲引擎會根據表的使用狀況自動爲表生成哈希索引,不能人爲干預是否在一張表中生成哈希索引。
傳統意義上的索引就是指的B+樹索引,這是目前關係型數據庫系統中查找最爲經常使用和有效的索引,其構造就是採用了二叉樹的思想,根據鍵值對快速找到數據。經過B+樹索引找到被查找數據行所在的頁,而後數據庫把頁讀入到內存,再在內存中進行查找,找到對應的數據。
InnoDB使用的是行鎖,只有在修改行時,纔會對行進行加鎖。使用索引可以使得數據在查詢過程當中鎖定更少的行,增長了數據處理的併發性,提升了數據庫的性能。
select id from article where id+1=5
等狀況的出現,不然索引將不能使用。pt-duplicate-key-checker h=127.0.0.1
查找重複和冗餘的索引,而後將重複冗餘的索引刪除。MySQL鏈接狀態
MySQL客戶端和服務器之間的通訊協議是"半雙工"的,在任何一個時刻,要麼是由服務器向客戶端發送數據,要麼是由客戶端向服務器端發送數據,兩個動做不能同時發生。對於每個時刻,能夠經過命令show full processlist
來查看mysql當前鏈接的狀態(Command列就表明當前的狀態)。
MySQL的狀態以下:
Sleep: 線程正在等待客戶端發送新的請求
Query: 線程正在執行查詢或者正在將結果發送給客戶端。
Locked: 在MySQL服務器層,該線程正在等待表鎖.
Sorting result: 線程正在對結果集進行排序。
Copying to tmp table [on disk]: 線程正在執行查詢,而且將其結果集都複製到一個臨時表中,這種狀態要麼是在作GROUP BY操做,要麼是文件排序操做,或者是UNION操做。若是狀態上有on disk的標記,那麼表示MySQL正在將一個內存臨時表放到磁盤上。
Analyzing and statistics: 線程正在收集存儲引擎的統計信息,並生成查詢的執行計劃。
Sending data: 這表示線程或者在多個狀態之間傳送數據,或者在生成結果集,或者在向客戶端返回數據。
MySQL鏈接過程
在上面MySQL執行查詢的過程當中,服務器已經提供了一些SQL的優化措施,咱們也須要正確理解並使用這些個優化措施
show status like 'last_query_cost'
能夠查詢當前會話的last_query_cost值來得知mysql計算的當前查詢的成本,mysql會進行評估並獲得成本最小的執行計劃。優化數據訪問的關鍵在於:減小數據訪問量,只檢索必要訪問的數據,保證向數據庫發出的查詢數據量只是實際須要的數據量。
爲了實現數據訪問量的優化,可使用: