1. MySQL如何使用索引html
索引用於快速查找具備特定列值的行。若是沒有索引,MySQL必須從第一行開始,而後遍歷整個表以找到相關的行。表越大,花費越多。若是表中有相關列的索引,MySQL能夠快速肯定要在數據文件中間查找的位置,而沒必要查看全部數據。這比順序讀取每一行要快得多。mysql
大多數MySQL索引(PRIMARY KEY,UNIQUE,INDEX和FULLTEXT)存儲在B樹(B-tree)中。例外狀況:空間數據類型的索引使用R樹; MEMORY表還支持哈希索引。 InnoDB對FULLTEXT索引使用倒排列表。sql
MySQL使用索引進行如下操做:數據庫
最後,索引對小表的查詢不過重要。當查詢須要訪問大多數行時,順序讀取比處理索引快。緩存
2. 避免全表掃描服務器
當MySQL使用全表掃描來解析查詢時,EXPLAIN的輸出在type列中顯示ALL。 這一般在如下狀況下發生:數據結構
對於小表,表掃描一般是合適的,而且對性能的影響能夠忽略不計。 性能
對於大表,能夠嘗試如下技術,以免優化器錯誤地選擇表掃描:測試
3. 列索引優化
B樹(B-tree)數據結構使索引能夠在WHERE子句中快速找到與運算符(例如=,>,≤,BETWEEN,IN等)相對應的特定值,一組值或一系列值。
每一個存儲引擎都會定義每一個表的最大索引數和最大索引長度。全部存儲引擎支持每一個表至少16個索引,而且索引總長度至少爲256個字節。
索引前綴
用col_name(N)能夠建立僅使用列的前N個字符的索引。在InnoDB表中,前綴最長767字節。
全文索引
FULLTEXT索引用於全文搜索。僅InnoDB和MyISAM存儲引擎支持FULLTEXT索引,而且僅支持CHAR,VARCHAR和TEXT列。索引始終在整個列上進行,而且不支持列前綴索引。
空間索引
指依據空間對象的位置和形狀或空間對象之間的某種空間關係按必定的順序排列的一種數據結構
MEMORY存儲引擎上的索引
默認狀況下,MEMORY存儲引擎使用HASH索引,但也支持BTREE索引。
4. 多列索引
MySQL能夠建立複合索引(即多列上的索引)。 一個索引最多能夠包含16列。
假設有一張表示這樣定義的:
CREATE TABLE test ( id INT NOT NULL, last_name CHAR(30) NOT NULL, first_name CHAR(30) NOT NULL, PRIMARY KEY (id), INDEX idx_name (last_name,first_name) );
idx_name索引是創建在last_name和first_name列之上的索引,該索引能夠用於指定了last_name和first_name值組合的查詢,也能夠用於僅指定last_name值的查詢,由於該索引是最左前綴匹配的。
所以,idx_name索引能夠用於下列查詢:
SELECT * FROM test WHERE last_name='Jones'; SELECT * FROM test WHERE last_name='Jones' AND first_name='John'; SELECT * FROM test WHERE last_name='Jones' AND (first_name='John' OR first_name='Jon'); SELECT * FROM test WHERE last_name='Jones' AND first_name >='M' AND first_name < 'N';
然而,idx_name索引不能用於下列查詢:
SELECT * FROM test WHERE first_name='John'; SELECT * FROM test WHERE last_name='Jones' OR first_name='John';
考慮下面的SQL:
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
若是在col1和col2上存在一個多列索引,那麼能夠直接抓取適當的行。若是col1和col2上分別存在單獨的單列索引,則優化器將嘗試使用索引合併優化,或者經過肯定哪一個索引須要排除更多行來查找限制性最強的索引,並使用該索引來獲取行。
若是表具備多列索引,那麼優化器可使用該索引的任何最左前綴來查找行。例如,若是有一個三列索引(col1, col2, col3),那麼在(col1), (col1, col2), (col1, col2, col3) 上具備索引搜索功能。
若是列不構成索引的最左前綴,則MySQL沒法使用索引執行查找。
再看下面的SQL語句:
SELECT * FROM tbl_name WHERE col1=val1; SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; SELECT * FROM tbl_name WHERE col2=val2; SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
若是在(col1, col2, col3)上存在複合索引,那麼只有前兩個查詢會使用。然後最後兩個查詢不會使用索引來執行查找,由於(col2)和(col2,col3)並非(col1,col2,col3)的最左前綴。
5. B-Tree 和 Hash 索引的比較
B樹索引特徵
B樹(B-tree)索引可用於使用=,>,>=,<,<=,BETWEEN運算符的表達式中的列比較。若是LIKE的參數是一個不以通配符開頭的常量字符串,則該索引也能夠用於LIKE比較。
下列這些子句不會使用索引:
/* the LIKE value begins with a wildcard character */ SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%'; /* the LIKE value is not a constant */ SELECT * FROM tbl_name WHERE key_col LIKE other_col;
沒有覆蓋WHERE子句中全部AND級別的任何索引都不會用於優化查詢。換句話說,爲了可以使用索引,必須在每一個AND組中使用索引的前綴。
下列WHERE子句會使用索引:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3 /* index = 1 OR index = 2 */ ... WHERE index=1 OR A=10 AND index=2 /* optimized like "index_part1='hello'" */ ... WHERE index_part1='hello' AND index_part3=5 /* Can use index on index1 but not on index2 or index3 */ ... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;
下面這些WHERE子句不會使用索引:
/* index_part1 is not used */ ... WHERE index_part2=1 AND index_part3=2 /* Index is not used in both parts of the WHERE clause */ ... WHERE index=1 OR A=10 /* No index spans all rows */ ... WHERE index_part1=1 OR index_part2=10
有時,即便有可用的索引,MySQL也不使用索引。發生這種狀況的一種可能緣由是,優化器估計使用索引將須要訪問表中很大比例的行。(在這種狀況下,表掃描可能會更快,由於它須要更少的查找。)可是,若是這樣的查詢使用LIMIT只檢索某些行,則MySQL仍然使用索引,由於它能夠更快地找到返回結果的幾行。
哈希索引特徵
哈希索引與剛剛討論的索引具備一些不一樣的特徵:
B-tree
樹型數據結構,普遍用於數據庫索引中。該結構始終保持有序,從而能夠快速查找精確匹配(等於運算符)和範圍(例如,大於,小於和BETWEEN運算符)。 此類索引可用於大多數存儲引擎,例如InnoDB和MyISAM。
由於B樹節點能夠有不少子節點,因此B樹與二叉樹不一樣,後者的每一個節點最多隻能有2個子節點。
術語B樹的使用旨在參考索引設計的通常類別。因爲經典B樹設計中不存在複雜性,MySQL存儲引擎使用的B樹結構可能被視爲變體。
Hash index
一種索引類型,專用於使用相等運算符而不是範圍運算符的查詢。 它可用於MEMORY表。 儘管出於歷史緣由,哈希索引是MEMORY表的默認索引,可是該存儲引擎還支持B樹索引,對於通常用途的查詢而言,B樹索引一般是更好的選擇。
6. 優化數據大小
設計表以使得它們在磁盤上佔用最少的空間。 經過減小寫入磁盤和從磁盤讀取的數據量,這能夠帶來巨大的改進。 較小的表一般在查詢執行期間處理其內容時須要較少的主內存。表數據的任何空間減小都會致使索引變小,從而能夠更快地處理索引。
MySQL支持許多不一樣的存儲引擎(表類型)和行格式。對於每一個表,能夠決定使用哪一種存儲和索引方法。爲應用程序選擇適當的表格式能夠大大提升性能。
Table Columns
Row Format
Indexes
Joins
Normalization
7. 優化數據類型
數值類型
字符和字符串類型
其它