從原理到優化,深刻淺出數據庫索引

MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。
數據庫查詢是數據庫的最主要功能之一,咱們都但願查詢數據的速度能儘量的快,所以數據庫系統的設計者會從查詢算法的角度進行優化,這篇文章對索引作一個系統的梳理,但願對你們有幫助。node

1、MySQL有哪些索引類型

索引的分類能夠從多個角度進行,下面分別從數據結構,物理存儲和業務邏輯三個維度進行劃分。mysql

一、從數據結構角度

(1)B+樹索引(O(log(n)))

關於B+樹索引,後面會深刻解析算法

(2)hash索引

  • 僅僅能知足"=","IN"和"<=>"查詢,不能使用範圍查詢
  • 其檢索效率很是高,索引的檢索能夠一次定位,不像B-Tree 索引須要從根節點到枝節點,最後才能訪問到頁節點這樣屢次的IO訪問,因此 Hash 索引的查詢效率要遠高於 B-Tree 索引
  • 只有Memory存儲引擎顯示支持hash索引

(3)FULLTEXT索引

如今MyISAM和InnoDB引擎都支持了sql

(4)R-Tree索引

用於對GIS數據類型建立SPATIAL索引數據庫

二、從物理存儲角度

(1)彙集索引(clustered index)

  • 正文內容按照一個特定維度排序存儲,這個特定的維度就是彙集索引;
  • Innodb存儲引擎中行記錄就是按照彙集索引維度順序存儲的,Innodb的表也稱爲索引表;由於行記錄只能按照一個維度進行排序,因此一張表只能有一個彙集索引。

(2)非彙集索引(non-clustered index)

  • 索引是經過二叉樹的數據結構來描述的,咱們能夠這麼理解聚簇索引:索引的葉節點就是數據節點。而非聚簇索引的葉節點仍然是索引節點,只不過有一個指針指向對應的數據塊。服務器

  • 非彙集索引索引項順序存儲,但索引項對應的內容倒是隨機存儲的;

舉個例子說明下:數據結構

create table student (
`id` INT UNSIGNED AUTO_INCREMENT,
`name` VARCHAR(255),
PRIMARY KEY(`id`),
KEY(`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

該表中主鍵id是該表的彙集索引、name爲非彙集索引;表中的每行數據都是按照彙集索引id排序存儲的;好比要查找name='Arla'和name='Arle'的兩個同窗,他們在name索引表中位置多是相鄰的,可是實際存儲位置可能差的很遠。name索引表節點按照name排序,檢索的是每一行數據的主鍵。彙集索引表按照主鍵id排序,檢索的是每一行數據的真實內容。數據結構和算法

三、從邏輯角度

(1)主鍵索引

主鍵索引是一種特殊的惟一索引,不容許有空值ide

(2)普通索引或者單列索引

(3)多列索引(複合索引)

複合索引指多個字段上建立的索引,只有在查詢條件中使用了建立索引時的第一個字段,索引纔會被使用。使用複合索引時遵循最左前綴集合性能

(4)惟一索引或者非惟一索引

(5)空間索引

空間索引是對空間數據類型的字段創建的索引,MYSQL中的空間數據類型有4種,分別是GEOMETRY、POINT、LINESTRING、POLYGON。

MYSQL使用SPATIAL關鍵字進行擴展,使得可以用於建立正規索引類型的語法建立空間索引。建立空間索引的列,必須將其聲明爲NOT NULL,空間索引只能在存儲引擎爲MYISAM的表中建立.

2、索引建立方式

CREATE TABLE table_name[col_name data type]
[unique|fulltext|spatial][index|key][index_name](col_name[length])[asc|desc]
  • unique|fulltext|spatial爲可選參數,分別表示惟一索引、全文索引和空間索引;
  • index和key爲同義詞,二者做用相同,用來指定建立索引
  • col_name爲須要建立索引的字段列,該列必須從數據表中該定義的多個列中選擇;
  • index_name指定索引的名稱,爲可選參數,若是不指定,MYSQL默認col_name爲索引值;length爲可選參數,表示索引的長度,只有字符串類型的字段才能指定索引長度;
  • asc或desc指定升序或降序的索引值存儲

一、建立表時創建索引

(1)建立普通索引

create table table_name(
    id int(11),
    name varchar(20),
    sex boolean,
    INDEX(id)
);

查看錶結構

show create table table_name;
可使 EXPLAIN 語句查看索引是否被使用

explain select * from table_name where id = 1\G

(2)建立惟一索引

create table index2(
    id int unique,
    name varchar(20),
    unique INDEX index_2(id asc)
);

(3)建立全文索引

全文索引只能在char,varchar或者text 類型的字段上。並且,只有MyISAM 儲存引擎支持全文索引。

create table idnex3(
    id int,
    info varchar(20),
    FULLTEXT INDEX index3_info(info)
)ENGINE=MyISAM;

(4)建立單列索引

create table index4(
    id int,
    subject varchar(255),
    index index4_st(subject(10))
);

這裏須要注意的,subject 的長度爲255,可是index4_st索引只有10。這樣作的目的仍是爲了提升查詢速度。對於字符型的數據,能夠不用查詢所有信息,只查詢其前面的若干字符信息。

(5)建立多列索引

create table index5(
    id int,
    name varchar(20),
    sex char(4),
    index index5_ns(name.sex)
);

這是咱們能夠看到,name 和sex字段上已經建立了index_ns索引。

二、在已經存在的表中建立索引

(1)建立普通索引

在example0() 表中的id 建立名爲index7_id 的索引。

create index index7_id on example0(id);

(2)建立惟一索引

create UNIQUE index index_name on table_name(name);

(3)建立全文索引

create FULLTEXT index index_name on table_name(info);

(4)建立單列索引

create INDEX index_name ON table_name(name(10));

(5)建立多列索引

create INDEX index_name ON table_name(name,sex);

三、用alter table 語句來建立索引

(1)建立普通索引

在name字段上建立名爲indx_name 的索引

alter table table_name ADD INDEX index_name(name(20));

(2)建立惟一性索引

alter table table_name ADD UNIQUE INDEX index_name(id);

(3)建立全文索引

alter table table_name ADD FULLTEXT INDEX index_name(info);

(4)建立單列索引

alter table table_name ADD INDEX index_name(name(4));

(5)建立多列索引

alter tabel table_name ADD INDEX index_name(name.sex);

四、刪除索引

DROP INDEX index_name ON table_name;

3、索引樹是如何維護的

目前大部分數據庫系統及文件系統都採用B-Tree或其變種B+Tree做爲索引結構,那麼索引樹是如何維護的?

一、查找結構進化史

查找是數據結構和算法中一個很是重要的概念。

  • 線性查找:一個個找;實現簡單;太慢
  • 二分查找:有序;簡單;要求是有序的,插入特別慢
  • HASH查找:查詢快;佔用空間;不太適合存儲大規模數據
  • 二叉查找樹:插入和查詢很快(log(n));沒法存大規模數據,複雜度退化
  • 平衡樹:解決 BST 退化問題,樹是平衡的;節點很是多的時候,依然樹高很高
  • 多路查找樹:一個父親多個孩子節點(度);節點過多樹高不會特別深
  • 多路平衡查找樹:B-Tree

二、B-Tree

B-Tree是一種多路搜索樹(並非二叉的):

  1. 定義任意非葉子結點最多隻有M個兒子;且M>2;
  2. 根結點的兒子數爲[2, M];
  3. 除根結點之外的非葉子結點的兒子數爲[M/2, M];
  4. 每一個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)
  5. 非葉子結點的關鍵字個數=指向兒子的指針個數-1;
  6. 非葉子結點的關鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
  7. 非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小於K[1]的
    子樹,P[M]指向關鍵字大於K[M-1]的子樹,其它P[i]指向關鍵字屬於(K[i-1], K[i])的子樹;
  8. 全部葉子結點位於同一層;
  9. 每一個k對應一個data。
    如:(M=3)至關於一個2–3樹,2–3樹是一個這樣的一棵樹, 它的每一個節點要麼有2個孩子和1個數據元素,要麼有3個孩子和2個數據元素,葉子節點沒有孩子,而且有1個或2個數據元素。

從原理到優化,深刻淺出數據庫索引

B-樹的搜索,從根結點開始,對結點內的關鍵字(有序)序列進行二分查找,若是命中則結束,不然進入查詢關鍵字所屬範圍的兒子結點;重複,直到所對應的兒子指針爲空,或已是葉子結點;B-Tree上查找算法的僞代碼以下:

BTree_Search(node, key) { if(node == null) return null; foreach(node.key) { if(node.key[i] == key) return node.data[i]; if(node.key[i] > key) return BTree_Search(point[i]->node); } return BTree_Search(point[i+1]->node); } data = BTree_Search(root, my_key);

(1)B-樹的特性

  1. 關鍵字集合分佈在整顆樹中;
  2. 任何一個關鍵字出現且只出如今一個結點中;
  3. 搜索有可能在非葉子結點結束;
  4. 其搜索性能等價於在關鍵字全集內作一次二分查找;
  5. 自動層次控制;

(2)B-樹的自控制

B樹中每個內部節點會包含必定數量的鍵值。一般,鍵值的數量被選定在d和2d之間。在實際中,鍵值佔用了節點中大部分的空間。因數2將保證節點能夠被拆分或組合。若是一個內部節點有2d個鍵值,那麼添加一個鍵值給此節點的過程,將會拆分2d鍵值爲2個d鍵值的節點,並把此鍵值添加給父節點。每個拆分的節點須要最小數目的鍵值。類似地,若是一個內部節點和他的鄰居二者都有d個鍵值,那麼將經過它與鄰居的合併來刪除一個鍵值。刪除此鍵值將致使此節點擁有d-1個鍵值;與鄰居的合併則加上d個鍵值,再加上從鄰居節點的父節點移來的一個鍵值。結果爲徹底填充的2d個鍵值。

(3)B-樹的構造過程

下面是往B樹中依次插入

6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4

從原理到優化,深刻淺出數據庫索引

三、B+Tree

B-Tree有許多變種,其中最多見的是B+Tree,MySQL就廣泛使用B+Tree實現其索引結構。
與B-Tree相比,B+Tree有如下不一樣點:

  1. 非葉子結點的子樹指針與關鍵字個數相同;
  2. 非葉子結點的子樹指針P[i],指向關鍵字值屬於[K[i], K[i+1])的子樹(B-樹是開區間);
  3. 爲全部葉子結點增長一個鏈指針;
  4. 全部關鍵字都在葉子結點出現;
  5. 內節點不存儲data,只存儲key
    如:(M=3)

從原理到優化,深刻淺出數據庫索引

B+的搜索與B-樹也基本相同,區別是B+樹只有達到葉子結點才命中(B-樹能夠在非葉子結點命中),其性能也等價於在關鍵字全集作一次二分查找;

(1)B+的特性

  1. 全部關鍵字都出如今葉子結點的鏈表中(稠密索引),且鏈表中的關鍵字剛好是有序的;
  2. 不可能在非葉子結點命中;
  3. 非葉子結點至關因而葉子結點的索引(稀疏索引),葉子結點至關因而存儲(關鍵字)數據的數據層;
  4. 更適合文件索引系統;

(2)B+樹的構造過程

下面是往B+樹中依次插入

6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4

從原理到優化,深刻淺出數據庫索引

三、索引的物理存儲

通常來講,索引自己也很大,不可能所有存儲在內存中,所以索引每每以索引文件的形式存儲的磁盤上。

這樣的話,索引查找過程當中就要產生磁盤I/O消耗,相對於內存存取,I/O存取的消耗要高几個數量級,因此評價一個數據結構做爲索引的優劣最重要的指標就是在查找過程當中磁盤I/O操做次數的漸進複雜度。換句話說,索引的結構組織要儘可能減小查找過程當中磁盤I/O的存取次數。

假如每一個盤塊能夠正好存放一個B樹的結點(正好存放2個文件名)。那麼一個BTNODE結點就表明一個盤塊,而子樹指針就是存放另一個盤塊的地址。

(1)模擬B+樹查找過程

下面,我們來模擬下查找文件29的過程:

從原理到優化,深刻淺出數據庫索引

  1. 根據根結點指針找到文件目錄的根磁盤塊1,將其中的信息導入內存。【磁盤IO操做 1次】
  2. 此時內存中有兩個文件名1七、35和三個存儲其餘磁盤頁面地址的數據。根據算法咱們發現:17<29<35,所以咱們找到指針p2。
  3. 根據p2指針,咱們定位到磁盤塊3,並將其中的信息導入內存。【磁盤IO操做 2次】
  4. 此時內存中有兩個文件名26,30和三個存儲其餘磁盤頁面地址的數據。根據算法咱們發現:26<29<30,所以咱們找到指針p2。
  5. 根據p2指針,咱們定位到磁盤塊8,並將其中的信息導入內存。【磁盤IO操做 3次】
  6. 此時內存中有兩個文件名28,29。根據算法咱們查找到文件名29,並定位了該文件內存的磁盤地址。
    分析上面的過程,發現須要3次磁盤IO操做和3次內存查找操做。關於內存中的文件名查找,因爲是一個有序表結構,能夠利用折半查找提升效率。至於IO操做是影響整個B樹查找效率的決定因素。
    固然,若是咱們使用平衡二叉樹的磁盤存儲結構來進行查找,磁盤4次,最多5次,並且文件越多,B樹比平衡二叉樹所用的磁盤IO操做次數將越少,效率也越高。

四、B+tree的優勢

(1)B+-tree的磁盤讀寫代價更低

B+-tree的內部結點並無指向關鍵字具體信息的指針。所以其內部結點相對B 樹更小。若是把全部同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的須要查找的關鍵字也就越多。相對來講IO讀寫次數也就下降了。
舉個例子,假設磁盤中的一個盤塊容納16bytes,而一個關鍵字2bytes,一個關鍵字具體信息指針2bytes。一棵9階B-tree(一個結點最多8個關鍵字)的內部結點須要2個盤快。而B+
樹內部結點只須要1個盤快。當須要把內部結點讀入內存中的時候,B 樹就比B+樹多一次盤塊查找時間(在磁盤中就是盤片旋轉的時間)。

(2)B+-tree的查詢效率更加穩定

因爲非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。

4、索引建立有哪些原則

索引查詢是數據庫中重要的記錄查詢方法,要不要進入索引以及在那些字段上創建索引都要和實際數據庫系統的查詢要求結合來考慮,下面給出實際中的一些通用的原則:

  1. 在常常用做過濾器的字段上創建索引;
  2. 在SQL語句中常常進行GROUP BY、ORDER BY的字段上創建索引;
  3. 在不一樣值較少的字段上沒必要要創建索引,如性別字段;
  4. 對於常常存取的列避免創建索引;
  5. 用於聯接的列(主健/外健)上創建索引;
  6. 在常常存取的多個列上創建複合索引,但要注意複合索引的創建順序要按照使用的頻度來肯定;
  7. 缺省狀況下創建的是非簇集索引,但在如下狀況下最好考慮簇集索引,如:含有有限數目(不是不多)惟一的列;進行大範圍的查詢;充分的利用索引能夠減小表掃描I/0的次數,有效的避免對整表的搜索。
  8. 常常用在WHERE子句中的數據列;
  9. 常常出如今關鍵字order by、group by、distinct後面的字段,創建索引。若是創建的是複合索引,索引的字段順序要和這些關鍵字後面的字段順序一致,不然索引不會被使用;
  10. 對於那些查詢中不多涉及的列,重複值比較多的列不要創建索引;
  11. 對於定義爲text、image和bit的數據類型的列不要創建索引;
  12. 對於常常存取的列避免創建索引;
  13. 限制表上的索引數目。對一個存在大量更新操做的表,所建索引的數目通常不要超過3個,最多不要超過5個。索引雖然說提升了訪問速度,但太多索引會影響數據的更新操做。
  14. 對複合索引,按照字段在查詢條件中出現的頻度創建索引。在複合索引中,記錄首先按照第一個字段排序。對於在第一個字段上取值相同的記錄,系統再按照第二個字段的取值排序,以此類推。所以只有複合索引的第一個字段出如今查詢條件中,該索引纔可能被使用,所以將應用頻度高的字段,放置在複合索引的前面,會使系統最大可能地使用此索引,發揮索引的做用。

一、組合多個索引

一個單獨的索引掃描只能用於這樣的條件子句:使用被索引字段和索引操做符類中的操做符, 而且這些條件以AND鏈接。

假設在(a, b)上有一個索引, 那麼相似WHERE a = 5 AND b = 6的條件可使用索引,可是像WHERE a = 5 OR b = 6的條件就不能直接使用索引。

一個相似WHERE x =42 OR x = 47 OR x = 53 OR x = 99 這樣的查詢能夠分解成四個在x上的獨立掃描,每一個掃描使用一個條件, 最後將這些掃描的結果OR 在一塊兒,生成最終結果。

另一個例子是,若是咱們在x 和y上有獨立的索引,一個相似WHERE x = 5 AND y = 6 這樣的查詢能夠分解爲幾個使用獨立索引的子句,而後把這幾個結果AND 在一塊兒,生成最終結果。

5、索引失效有哪幾種狀況

  1. 若是條件中有or,即便其中有條件帶索引也不會使用(這也是爲何儘可能少用or的緣由)
  2. 對於多列索引,不是使用的第一部分(第一個),則不會使用索引
  3. like查詢是以%開頭
  4. 若是列類型是字符串,那必定要在條件中將數據使用引號引用起來,不然不使用索引
  5. 若是mysql估計使用全表掃描要比使用索引快,則不使用索引

一、聯合索引失效的條件

聯合索引又叫複合索引。兩個或更多個列上的索引被稱做複合索引。

對於複合索引:Mysql從左到右的使用索引中的字段,一個查詢能夠只使用索引中的一部份,但只能是最左側部分。例如索引是key index (a,b,c)。 能夠支持a | a,b| a,b,c 3種組合進行查找,但不支持 b,c進行查找 .當最左側字段是常量引用時,索引就十分有效。

因此說建立複合索引時,應該仔細考慮列的順序。對索引中的全部列執行搜索或僅對前幾列執行搜索時,複合索引很是有用;僅對後面的任意列執行搜索時,複合索引則沒有用處。

6、如何查看索引的使用狀況

這裏記錄兩種方式,分別是

一、使用Handler_read查看索引的使用狀況

show status like ‘Handler_read%';

你們能夠注意:

  • handler_read_key:這個值越高越好,越高表示使用索引查詢到的次數
  • handler_read_rnd_next:這個值越高,說明查詢低效
+-----------------------+--------------+
| Variable_name         | Value        |
+-----------------------+--------------+
| Handler_read_first    | 153      |
| Handler_read_key      | 364   |
| Handler_read_next     | 425    |
| Handler_read_prev     | 598     |
| Handler_read_rnd      | 605     |
| Handler_read_rnd_next | 860571 |
+-----------------------+--------------+
6 rows in set (0.00 sec)
————————————————

分析這幾個值,咱們能夠查看當前索引的使用狀況:

  • Handler_read_first:索引中第一條被讀的次數。若是較高,它表示服務器正執行大量全索引掃描;例如,SELECT col1 FROM foo,假定col1有索引(這個值越低越好)。
  • Handler_read_key:若是索引正在工做,這個值表明一個行被索引值讀的次數,若是值越低,表示索引獲得的性能改善不高,由於索引不常用(這個值越高越好)。
  • Handler_read_next :按照鍵順序讀下一行的請求數。若是你用範圍約束或若是執行索引掃描來查詢索引列,該值增長。
  • Handler_read_prev:按照鍵順序讀前一行的請求數。該讀方法主要用於優化ORDER BY ... DESC。
  • Handler_read_rnd :根據固定位置讀一行的請求數。若是你正執行大量查詢並須要對結果進行排序該值較高。你可能使用了大量須要MySQL掃描整個表的查詢或你的鏈接沒有正確使用鍵。這個值較高,意味着運行效率低,應該創建索引來補救。
  • Handler_read_rnd_next:在數據文件中讀下一行的請求數。若是你正進行大量的表掃描,該值較高。一般說明你的表索引不正確或寫入的查詢沒有利用索引。

二、在sys庫中查看沒用的索引

查詢 schema_unused_indexes庫。

root@localhost [sys]>select * from schema_unused_indexes;
+-------------------+-------------+------------+
| object_schema     | object_name | index_name |
+-------------------+-------------+------------+
| sysbench_testdata | sbtest1     | k_1        |
| sysbench_testdata | sbtest10    | k_10       |
| sysbench_testdata | sbtest3     | k_3        |
| sysbench_testdata | sbtest4     | k_4        |
| sysbench_testdata | sbtest5     | k_5        |
| sysbench_testdata | sbtest6     | k_6        |
| sysbench_testdata | sbtest7     | k_7        |
| sysbench_testdata | sbtest8     | k_8        |
| sysbench_testdata | sbtest9     | k_9        |
+-------------------+-------------+------------+
9 rows in set (0.00 sec)

7、EXPLAIN解釋命令查看索引是否生效

explain顯示了mysql如何使用索引來處理select語句以及鏈接表。能夠幫助選擇更好的索引和寫出更優化的查詢語句。

一、一個實際例子

新建一張表,

CREATE TABLE IF NOT EXISTS `article` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`author_id` int(10) unsigned NOT NULL,
`category_id` int(10) unsigned NOT NULL,
`views` int(10) unsigned NOT NULL,
`comments` int(10) unsigned NOT NULL,
`title` varbinary(255) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`)
);

執行查詢,

EXPLAIN
SELECT author_id
FROM `article`
WHERE category_id = 1 AND comments > 1
ORDER BY views DESC
LIMIT 1

響應數據以下,

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: article
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 3
        Extra: Using where; Using filesort
1 row in set (0.00 sec)

type 是 ALL,即最壞的狀況。Extra 裏還出現了 Using filesort,也是最壞的狀況。

二、EXPLAIN列的解釋:

  • table:顯示這一行的數據是關於哪張表的
  • type:這是重要的列,顯示鏈接使用了何種類型。從最好到最差的鏈接類型爲const、eq_reg、ref、range、indexhe和ALL
  • possible_keys:顯示可能應用在這張表中的索引。若是爲空,沒有可能的索引。能夠爲相關的域從WHERE語句中選擇一個合適的語句
  • key: 實際使用的索引。若是爲NULL,則沒有使用索引。不多的狀況下,MYSQL會選擇優化不足的索引。這種狀況下,能夠在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
  • key_len:使用的索引的長度。在不損失精確性的狀況下,長度越短越好
  • ref:顯示索引的哪一列被使用了,若是可能的話,是一個常數
  • rows:MYSQL認爲必須檢查的用來返回請求數據的行數
  • Extra:關於MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這裏能夠看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結果是檢索會很慢

三、type返回結果的解釋

MySQL 在表裏找到所需行的方式。包括(由左至右,由最差到最好):
| All | index | range | ref | eq_ref | const,system | null |

  • system 表只有一行:system表。這是const鏈接類型的特殊狀況
  • const:表中的一個記錄的最大值可以匹配這個查詢(索引能夠是主鍵或唯一索引)。由於只有一行,這個值實際就是常數,由於MYSQL先讀這個值而後把它當作常數來對待
  • eq_ref:在鏈接中,MYSQL在查詢時,從前面的表中,對每個記錄的聯合都從表中讀取一個記錄,它在查詢使用了索引爲主鍵或唯一鍵的所有時使用
  • ref:這個鏈接類型只有在查詢使用了不是唯一或主鍵的鍵或者是這些類型的部分(好比,利用最左邊前綴)時發生。對於以前的表的每個行聯合,所有記錄都將從表中讀出。這個類型嚴重依賴於根據索引匹配的記錄多少—越少越好
  • range:這個鏈接類型使用索引返回一個範圍中的行,好比使用>或<查找東西時發生的狀況
  • index: 這個鏈接類型對前面的表中的每個記錄聯合進行徹底掃描(比ALL更好,由於索引通常小於表數據)
  • ALL:這個鏈接類型對於前面的每個記錄聯合進行徹底掃描,這通常比較糟糕,應該儘可能避免

四、extra列返回的描述的意義

  • Distinct:一旦MYSQL找到了與行相聯合匹配的行,就再也不搜索了
  • Not exists: MYSQL優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就再也不搜索了
  • Range checked for each Record(index map:#):沒有找到理想的索引,所以對於從前面表中來的每個行組合,MYSQL檢查使用哪一個索引,並用它來從表中返回行。這是使用索引的最慢的鏈接之一
  • Using filesort: 看到這個的時候,查詢就須要優化了。MYSQL須要進行額外的步驟來發現如何對返回的行排序。它根據鏈接類型以及存儲排序鍵值和匹配條件的所有行的行指針來排序所有行
  • Using index: 列數據是從僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,這發生在對錶的所有的請求列都是同一個索引的部分的時候
  • Using temporary 看到這個的時候,查詢須要優化了。這裏,MYSQL須要建立一個臨時表來存儲結果,這一般發生在對不一樣的列集進行ORDER BY上,而不是GROUP BY上
  • Using where 使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。若是不想返回表中的所有行,而且鏈接類型ALL或index,這就會發生,或者是查詢有問題不一樣鏈接類型的解釋(按照效率高低的順序排序)
相關文章
相關標籤/搜索