日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL——索引与EXPLAIN

發(fā)布時間:2023/12/8 数据库 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL——索引与EXPLAIN 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

本文內(nèi)容主要參考自《高性能MySQL》第5章以及《MySQL DBA 修煉之道》書中的第三章,算是原書的實踐與補充。 上次主要講了MySQL的基本操作,這次來談?wù)勊饕cEXPLAIN。

I. 什么是索引?

想要深入的學(xué)習MySQL相關(guān)技術(shù),而不僅僅停留在簡單CURD,能夠?qū)懗霭偃f數(shù)據(jù)中分分鐘查出需要數(shù)據(jù)的SQL,首先就需要掌握索引技術(shù)。那么什么是索引呢?

要理解MySQL中索引是如何工作的,最簡單的方法就是去看看一本書的“索引”部分:如果想在一本書中找到某個特定主題,一般會先看書的“索引”,找到對應(yīng)的頁碼。所以當數(shù)據(jù)表中的數(shù)據(jù)越來越多時,挨個查找記錄將會越來越慢,我們需要像查“字典”一樣建立一種“目錄”,來幫我們?nèi)匀荒軌蚩焖俚牟檎蚁胍挠涗洝_@種“目錄”一樣的存在便是索引。在MySQL中,存儲引擎用類似的方法使用索引,其先在索引中找到對應(yīng)值,然后根據(jù)匹配的索引記錄找到數(shù)據(jù)庫表中對應(yīng)的數(shù)據(jù)行。

索引,在MySQL中也叫做“鍵(key)”,是存儲引擎用于快速找到記錄的一種數(shù)據(jù)結(jié)構(gòu)。為什么是數(shù)據(jù)結(jié)構(gòu)?因為本身索引是為了解決查找問題,查找排序在算法中是經(jīng)常遇到的,實現(xiàn)查找我們通常有一些對應(yīng)的算法,遍歷、二分、二叉搜索樹、紅黑樹、散列表等(詳細可以看橙色的那本《算法》書)。而一些快速的查找算法都有其對應(yīng)的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn),索引就是存儲引擎實現(xiàn)的一種數(shù)據(jù)結(jié)構(gòu)能夠快速用于查找數(shù)據(jù)庫中記錄。后面我們會知道數(shù)據(jù)結(jié)構(gòu)具體可能是 B-Tree、哈希索引、R-Tree、全文索引等。

索引優(yōu)化應(yīng)該是對查詢性能優(yōu)化最有效的手段了。索引能夠輕易將查詢性能提高幾個數(shù)量級,“最優(yōu)”的索引有時比一個“好的”索引性能要好兩個數(shù)量級。創(chuàng)建一個真正“最優(yōu)”的索引經(jīng)常需要重寫查詢。

同一個表,可以創(chuàng)建多個索引。就像新華字典的索引,不僅僅只有拼音,還有筆畫、偏旁部首等。除了允許不同的字段添加索引之外,還可以將字段組合添加索引,組合的先后順序也影響到查詢速度。甚至其實MySQL允許同一個字段上重復(fù)創(chuàng)建索引,但這并不可取。

II. 索引類型

對于數(shù)據(jù)庫索引相關(guān)問題來說,有許多計算機操作系統(tǒng)底層的名詞需要了解并通曉其含義,下面將本文需要提前了解的概念列出如下:

  • CPU密集型:CPU密集型也叫計算密集型,指的是系統(tǒng)的硬盤、內(nèi)存性能相對CPU要好很多,此時,系統(tǒng)運作大部分的狀況是CPU Loading 100%,CPU要讀/寫I/O(硬盤/內(nèi)存),I/O在很短的時間就可以完成,而CPU還有許多運算要處理,CPU Loading很高。

  • IO密集型:IO密集型指的是系統(tǒng)的CPU性能相對硬盤、內(nèi)存要好很多,此時,系統(tǒng)運作,大部分的狀況是CPU在等I/O (硬盤/內(nèi)存) 的讀/寫操作,沒有充分利用處理器能力。

  • 操縱系統(tǒng)頁:磁盤的讀寫速度比主存慢很多,所以為了提高效率,要盡量減少磁盤I/O,減少讀寫操作。為了達到這個目的,磁盤往往不是嚴格按需讀取,而是每次都會預(yù)讀,即使只需要一個字節(jié),磁盤也會從這個位置開始,順序向后讀取一定長度的數(shù)據(jù)放入內(nèi)存,這樣做的理論依據(jù)是計算機科學(xué)中著名的局部性原理。預(yù)讀的長度一般為頁(page)的整倍數(shù),頁是計算機管理存儲器的邏輯塊,硬件及操作系統(tǒng)往往將主存和磁盤存儲區(qū)分割為連續(xù)的大小相等的塊,每個存儲塊稱為一頁(在許多操作系統(tǒng)中,頁得大小通常為4k),主存和磁盤以頁為單位交換數(shù)據(jù)。當程序要讀取的數(shù)據(jù)不在主存中時,會觸發(fā)一個缺頁異常,此時系統(tǒng)會向磁盤發(fā)出讀盤信號,磁盤會找到數(shù)據(jù)的起始位置并向后連續(xù)讀取一頁或幾頁載入內(nèi)存中,然后異常返回,程序繼續(xù)運行。

  • 數(shù)據(jù)庫頁:數(shù)據(jù)庫文件存儲是頁為存儲單元,一個頁可以存放N行數(shù)據(jù)。我們常用的頁類型就是數(shù)據(jù)頁和索引頁。以InnoDB引擎為例,其邏輯存儲結(jié)構(gòu)如下圖所示。所有數(shù)據(jù)都被邏輯地存放在一個稱之為表空間 (tablespace)的空間中。表空間又由段(segment)區(qū)(extent)頁(page) 組成。表空間是由各個段組成的,常見的段有數(shù)據(jù)段、索引段、回滾段等。InnoDB存儲引擎表是索引組織的,因此數(shù)據(jù)即索引,索引即數(shù)據(jù)。那么數(shù)據(jù)段即為B+樹的葉子節(jié)點 (leaf node segment),索引段即為B+樹的非葉子節(jié)點 (non-leaf node segment)。區(qū)是由64個連續(xù)的頁組成的,每個頁大小為16KB,即每個區(qū)的大小為1MB。頁是InnoDB磁盤管理的最小單位。InnoDB存儲引擎是面向行的,也就是說數(shù)據(jù)的存放按行進行存放。每個頁存放的行記錄數(shù)目也是有硬性定義的,最多允許存放 16KB/2-200 行的記錄,即7992行記錄。

  • 順序IO:每次訪問磁盤的一個目標塊時,磁臂就需移動到正確的磁道上,耗費的這段時間為尋址時間;然后盤片就需旋轉(zhuǎn)到正確的扇區(qū)上,這段時間又為旋轉(zhuǎn)時延。很明顯總共耗費的時間依賴于磁頭的初使位置,還有要訪問的扇區(qū)的位置。如果目標塊剛好就在磁頭下方,那不需要等待;如果剛剛經(jīng)過磁頭,那就不得不等上一個周期時間。 找到上一個目標塊后,下一個目標塊就在剛才訪問的那一個磁盤塊的后面,磁頭能立刻遇到,不需等待,這種IO就叫順序IO。

  • 隨機IO:如果下一個目標塊在磁盤的另一個地方,訪問它會有同樣的尋道和旋轉(zhuǎn)時延,我們就把這種方式的IO叫做隨機IO。數(shù)據(jù)庫的很多設(shè)計也都是盡量充分利用順序IO,傳統(tǒng)的數(shù)據(jù)庫架構(gòu)對隨機IO幾乎沒有還手之力,隨機IO幾乎令所有DBA談虎色變,MySQL InnoDB則利用事務(wù)日志把隨機I/O轉(zhuǎn)成順序I/O。

  • 主存存取過程:從抽象角度看,主存是一系列的存儲單元組成的矩陣,每個存儲單元存儲固定大小的數(shù)據(jù)。每個存儲單元有唯一的內(nèi)存地址。當系統(tǒng)需要讀取主存時,則將地址信號放到地址總線上傳給主存,主存讀到地址信號后,解析信號并定位到指定存儲單元,然后將此存儲單元數(shù)據(jù)放到數(shù)據(jù)總線上,供其它部件讀取。寫主存的過程類似,系統(tǒng)將要寫入單元地址和數(shù)據(jù)分別放在地址總線和數(shù)據(jù)總線上,主存讀取兩個總線的內(nèi)容,做相應(yīng)的寫操作。這里可以看出,主存存取的時間僅與存取次數(shù)有關(guān),和存取的數(shù)據(jù)的位置沒什么關(guān)系,因為讀寫數(shù)據(jù)相當于直接根據(jù)地址定位坐標。

  • 磁盤存取過程:當需要從磁盤讀取數(shù)據(jù)時,系統(tǒng)會將數(shù)據(jù)邏輯地址傳給磁盤,磁盤的控制電路按照尋址邏輯將邏輯地址翻譯成物理地址,即確定要讀的數(shù)據(jù)在哪個磁道,哪個扇區(qū)。這個過程耗費的時間包括尋道和旋轉(zhuǎn)時間。由于存儲介質(zhì)的特性,磁盤本身存取就比主存慢很多,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分之一,因此為了提高效率,要盡量減少磁盤I/O。

索引是一中數(shù)據(jù)結(jié)構(gòu),那么索引類型自然是指不同類型的數(shù)據(jù)結(jié)構(gòu)。索引有很多種類型,可以為不同的場景提供更好的性能。在MySQL中,索引是在存儲引擎層而不是服務(wù)器層實現(xiàn)的。所以,并沒有統(tǒng)一的索引標準:不同存儲引擎的索引的工作方式并不一樣,也不是所有的存儲引擎都支持所有類型的索引。即使多個存儲引擎支持同一種類型的索引,其底層的實現(xiàn)也可能不同。我們主要來研究MySQL支持的索引類型。

B-Tree索引

當談索引的時候,如果沒有特別指明類型,那多半說的是B-Tree索引,它使用B-Tree數(shù)據(jù)結(jié)構(gòu)來存儲數(shù)據(jù)。那么首先我們先來了解B-Tree數(shù)據(jù)結(jié)構(gòu)。

① B樹,B-樹,B+樹

首先需要明確的是,B樹就是B-(減)樹,本文中凡是出現(xiàn)的B-Tree,都是B橫杠Tree,而非減號,如果想要表示B減樹則直接用漢字減或用B樹代表相同含義。

B樹

二叉查找樹是非平衡樹,極端情況下查找性能可能非常低,所以才有了紅黑樹這類平衡二叉樹。B樹也是一種平衡樹,相比于紅黑樹之類的2-3平衡樹而言,B樹的階,或者說是節(jié)點的最大出度不僅僅局限于2或3。從查找效率來說,一般階大于等于3,用 m 表示。假設(shè)一個非空的B樹,滿足以下性質(zhì):

  • 根結(jié)點至少有兩個子女;
  • 每個中間節(jié)點都包含 k-1 個元素和 k 個孩子,k 屬于 [ceil(m/2),m];
  • 每個葉子節(jié)點都包含 k-1 個元素,k 屬于 [ceil(m/2),m];
  • 所有的葉子節(jié)點都位于同一層(平衡樹);
  • 每個節(jié)點中的元素從小到大排列,節(jié)點當中 k-1 個元素正好是 k 個孩子包含的元素的值域劃分;
  • 每個節(jié)點包含了 k-1 個元素,以及 k 個孩子的指針。

一個標準的B樹如下圖:

可以看出當我們查找某一個元素時,最多需要讀取 h (B樹的高度) 次數(shù)即可。如果需要插入一條數(shù)據(jù),B樹為了維護上面的性質(zhì),需要對樹的結(jié)構(gòu)做一些調(diào)整。如果插入元素后某一節(jié)點的元素數(shù)目大于 m,則在插入前需要進行分裂。同樣,如果刪除一條數(shù)據(jù),刪除后節(jié)點的元素數(shù)目小于 ceil(m/2),也要進行相應(yīng)的合并操作。

利用B樹的數(shù)據(jù)結(jié)構(gòu)來進行存儲數(shù)據(jù),我們可以將數(shù)據(jù)與對應(yīng)的索引信息定義為一個組合[key, data],key是data的索引。那么一個簡單的B樹可以表示為:

每個節(jié)點中包含了 k-1 個索引值、 k-1 個對應(yīng)的數(shù)據(jù) (除去了索引值之外的數(shù)據(jù))以及 k 個指針指向子節(jié)點。

B+樹

B+樹其實是B樹的一種變種,MySQL普遍使用B+Tree的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)索引,當然包括主要存儲引擎MyISAM和InnoDB。B+樹與B樹相比,主要有以下不同:

  • 每個中間節(jié)點都包含 k 個元素和 k 個孩子,相當于指針數(shù)目也是 k;
  • 非葉子節(jié)點不存儲數(shù)據(jù)data,只存儲key;
  • 所有的中間節(jié)點元素都同時存在于子節(jié)點,在子節(jié)點元素中是最大(或最小)元素。

如下是一個B+樹的示意圖,可以看到完全滿足上面的三條性質(zhì)。

帶有順序訪問指針的B+樹

一般在數(shù)據(jù)庫系統(tǒng)或文件系統(tǒng)中使用的B+樹結(jié)構(gòu)都在經(jīng)典B+樹的基礎(chǔ)上進行了優(yōu)化,增加了順序訪問指針。下圖所示的帶有順序訪問指針的B+樹就是我們經(jīng)常看到的B+樹模樣。

對比上一幅圖,主要區(qū)別在于每個葉子節(jié)點增加一個指向相鄰葉子節(jié)點的指針,這樣就形成了帶有順序訪問指針的B+樹。這樣優(yōu)化的目的是為了提高區(qū)間訪問的性能,如果要查詢key為某個范圍內(nèi)的所有數(shù)據(jù)記錄,當找到第一個數(shù)據(jù)后,只需順著節(jié)點和指針順序遍歷就可以一次性訪問到所有數(shù)據(jù)節(jié)點,極大提到了區(qū)間查詢效率。

② 數(shù)據(jù)庫為什么使用B+樹?

數(shù)據(jù)庫的索引數(shù)據(jù)量也是很大的,所以它存儲在磁盤中,而非內(nèi)存。那么當進行增刪改查數(shù)據(jù)時,需要讀取索引內(nèi)容,就進行了磁盤I/O。通過前面的相關(guān)概念介紹,磁盤I/O的耗時操作越少越好,所以磁盤I/O次數(shù)可以評價索引數(shù)據(jù)結(jié)構(gòu)的優(yōu)劣。

先從二叉查找樹以及紅黑樹說起,這兩種樹本身的階數(shù)是固定的,每個節(jié)點的子節(jié)點數(shù)很小,導(dǎo)致了如果存在很多索引時,樹的深度非常深,對應(yīng)查找需要比較的次數(shù)也會非常多,性能必然受到嚴重影響。

再說B樹,因為它的階數(shù)是 m,可以設(shè)置的較大,這樣可以使的決定查詢比較次數(shù)的因素——樹的深度可以很淺。根據(jù)B樹的定義,可知檢索一次最多需要訪問 h 個節(jié)點。數(shù)據(jù)庫系統(tǒng)的設(shè)計者巧妙利用了磁盤預(yù)讀原理,將樹的每個節(jié)點的大小設(shè)為等于一個頁,這樣每個節(jié)點只需要一次磁盤I/O就可以完全載入。為了達到這個目的,在實際實現(xiàn)B樹時還需要使用如下技巧:

  • 每次新建節(jié)點時,直接申請一個頁的空間,這樣就保證一個節(jié)點物理上也存儲在一個頁里,加之計算機存儲分配都是按頁對齊的,就實現(xiàn)了一個節(jié)點只需一次磁盤I/O;
  • B樹中一次查詢最多需要 h-1 次磁盤I/O,因為根節(jié)點常駐于內(nèi)存,漸進復(fù)雜度為 O(h)=O(logdN)O(h)=O(log_dN)O(h)=O(logd?N)。一般實際應(yīng)用中,出度 d 是非常大的數(shù)字,通常超過100,因此 h 非常小 (通常不超過3,3已經(jīng)是10610^6106級別數(shù)據(jù)量)。

所以用B樹作為數(shù)據(jù)庫的索引效率遠遠高于紅黑樹等。

然而,MySQL的MyISAM和InnoDB都采用的是帶有順序訪問指針的B+樹去實現(xiàn)索引 ,這又是為何呢?比較B+樹和B樹的區(qū)別,除了葉子節(jié)點有順序訪問指針幫助范圍查詢之外,主要就是非葉子節(jié)點上B+樹只存有索引(key),沒有額外再存(data)。之前我們已經(jīng)說過,一般樹的每個節(jié)點的大小等于一個頁的大小,容量固定的情況下,由于B樹需要保存數(shù)據(jù)記錄所以一個節(jié)點能包含的索引數(shù)目比B+樹要小。也就是說,一個非葉子節(jié)點的出度 d,上限取決于節(jié)點內(nèi) key 和 data 的大小。具體的公式如下:

dmax=一個節(jié)點中能容納的索引數(shù)目=floor(pagesize/(keysize+datasize+pointsize))d_{max}=一個節(jié)點中能容納的索引數(shù)目=floor(pagesize/(keysize+datasize+pointsize))dmax?=節(jié)數(shù)=floor(pagesize/(keysize+datasize+pointsize))

由于B+樹非葉子節(jié)點去掉了 data,因此可以擁有更大的出度,擁有更好的性能。

③ MySQL中的B-Tree索引

《高性能MySQL》中一直使用的是B-Tree索引這樣的描述,從技術(shù)實現(xiàn)角度,其實是B+樹。

假設(shè)我們現(xiàn)在存在一個數(shù)據(jù)表,包含三個字段:主鍵Col1、輔助索引Col2以及字段Col3。

MyISAM索引實現(xiàn)

從上面對于B+樹的描述,我們可以大概的推測出索引的結(jié)構(gòu)。我們先來看MyISAM對于主鍵索引的原理圖:

可以看出MyISAM的B+樹中,非葉子節(jié)點僅僅保存了主鍵值,葉子節(jié)點上保存的是數(shù)據(jù)庫對應(yīng)記錄的地址。通過地址我們可以定位到每一條記錄。我們知道每個節(jié)點對應(yīng)一頁,每個節(jié)點中包含多行數(shù)據(jù)庫記錄 (圖中為2個),需要注意的是邏輯上相鄰的記錄,物理上可能并不在同一頁中,比如表中的第2行和第3行數(shù)據(jù),它們在不同的頁中。

我們再來看看輔助索引Col2的結(jié)構(gòu)。輔助索引的葉子結(jié)點除了包含鍵值以外,每個葉子結(jié)點中的索引行還包含了一個書簽,該書簽用來告訴存儲引擎可以在哪找到相應(yīng)的數(shù)據(jù)行,MyISAM存儲引擎的輔助索引的書簽就是地址,其實和主鍵索引沒什么差別。

同樣也是一顆B+樹,data域保存數(shù)據(jù)庫記錄的地址。因此,MyISAM中索引檢索的算法為首先按照B+樹搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址,讀取相應(yīng)數(shù)據(jù)記錄。

InnoDB索引實現(xiàn)

雖然InnoDB也使用B+樹作為索引結(jié)構(gòu),但具體實現(xiàn)方式卻與MyISAM截然不同。

首先來看主鍵索引的實現(xiàn)方式。

對比MyISAM的主鍵索引,最顯著的區(qū)別就是在于葉子節(jié)點的保存內(nèi)容。MyISAM索引文件和數(shù)據(jù)文件是分離的,索引文件僅保存數(shù)據(jù)記錄的地址。而在InnoDB中,表數(shù)據(jù)文件本身就是按B+樹組織的一個索引結(jié)構(gòu),這棵樹的葉節(jié)點data域保存了完整的數(shù)據(jù)記錄,這個索引的key是數(shù)據(jù)表的主鍵,那么InnoDB引擎的數(shù)據(jù)文件本身就是主索引文件。這種數(shù)據(jù)與索引在一起的結(jié)構(gòu)叫做聚簇索引,或者叫聚集索引。因為InnoDB的數(shù)據(jù)文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵。如果沒有顯式指定,則MySQL系統(tǒng)會自動選擇一個可以唯一標識數(shù)據(jù)記錄的列作為主鍵。如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵,這個字段長度為6個字節(jié),類型為長整型。

我們再來看看InnoDB的輔助索引實現(xiàn)結(jié)構(gòu),我們在表的Col3字段上添加上輔助索引。

與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應(yīng)記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域,因為通過主鍵我們同樣可以查詢到整個數(shù)據(jù)庫記錄。聚簇索引這種實現(xiàn)方式使得按主鍵的搜索十分高效,但是輔助索引查詢需要二次查詢:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

④ 正確使用和優(yōu)化索引

知道了索引的實現(xiàn)方式對我們理解索引的正確使用方式和優(yōu)化原理有著莫大的幫助。下面列舉一些使用索引的常見策略。

假設(shè)現(xiàn)在有一個表:

CREATE TABLE People (last_name varchar(50) not null,first_name varchar(50) not null,birth date not null,gender enum('m', 'f') not null,key(last_name, first_name, birth) );

表中定義了四個字段,包含姓、名、出生日期以及性別,同時建立了一個組合索引包含了姓、名、出生日期三個字段。該索引的B+樹結(jié)構(gòu)某一小部分如下:

可以看到非葉子節(jié)點上存儲了索引字段信息,B-Tree對索引列是順序組織存儲的,索引之間按照一定的排序規(guī)則進行有序的排序,這里就是按姓名的字母序以及日期的由小到大。依據(jù)這樣的一個結(jié)構(gòu),編寫合理的SQL語句,我們可以極為快速的尋找到我們需要的記錄。

  • 全值匹配:全值匹配指的是和索引中的所有列進行匹配,也就是我們的查詢語句的條件完全和索引列中一一對應(yīng),不僅僅是內(nèi)容,而且要求順序也一致。不難理解,這就是一個簡單的遞歸查找樹的過程。
  • 匹配最左前綴:當然我們想要從當前的索引樹中獲得好處,查詢條件并不一定需要全值匹配,我們可以只包含索引列中的第一個字段,例如我們查找所有姓Allen的人。當然,如果只包含名或生日的查詢條件,就不能利用當前索引樹了。
  • 匹配列前綴:同樣的,我們的查詢條件甚至可以連第一列字段的信息都不完全,比如只匹配第一列值的開頭部分。例如查找以姓All開頭的人。
  • 精確匹配某一列并范圍匹配另外一列:由前面的經(jīng)驗,我們自然就可以推演出,可以精確匹配前面部分的索引列,后面的索引列僅僅是最左前綴的形式。例如,我們要查找具體姓啥名啥但日期只要19xx年的人。
  • 匹配范圍值:匹配范圍值不光光能夠從索引樹整個結(jié)構(gòu)獲益,B+樹的葉子節(jié)點額外增加了順序訪問指針,使得速度能夠更快。這在之前我們已經(jīng)有所提及。
  • 覆蓋索引:覆蓋索引是指查詢只需要訪問索引,而無須訪問數(shù)據(jù)行。如果我們想要查詢的信息索引列已經(jīng)完全包含,那么我們就不需要再去葉子節(jié)點找到主鍵或者是記錄的地址,然后再到對應(yīng)的數(shù)據(jù)記錄中查詢信息。這樣一個過程其實叫二次查詢。
  • ORDER BY與GROUP BY:索引樹中的節(jié)點是有序的,所以除了按值查找之外,索引還可以用于查詢中的 ORDER BY 與 GROUP BY 操作。

當然,我們從之前的索引實現(xiàn)方式也能想到一些關(guān)于B-Tree索引的限制:

  • 如果不是按照索引的最左列開始查找,則無法使用索引。 例如上面例子中的索引無法用于直接查找名字為Bill的人,也無法直接查找某個特定生日的人,因為這兩列都不是最左前綴。類似地,也無法查找姓氏以某個字母結(jié)尾的人。
  • 不能跳過索引中的列。 也就是說,前面所述的索引無法用于查找姓為Smith并且在某個特定日期出生的人。如果不指定名字,則MySQL只能使用索引的第一列——姓列。
  • 如果查詢條件中有某個列是范圍查詢,則其右邊所有列都無法使用索引優(yōu)化查找。 如果范圍查詢列值的數(shù)量有限,那么可以通過使用多個等于條件來代替范圍條件。

哈希索引

① 什么是哈希索引?

哈希索引 (hash index) 是基于哈希表實現(xiàn)的,只有精確匹配索引所有列的查詢才有效。對于每一行數(shù)據(jù),存儲引擎都會對所有的索引列計算一個哈希碼 (hash code),哈希碼是一個較小的值,并且不同鍵值的行計算出來的哈希碼也不一樣。哈希索引將所有的哈希碼存儲在索引中,同時在哈希表中保存指向每個數(shù)據(jù)行的指針。

在MySQL中,只有Memory引擎顯式支持哈希索引。這也是Memory引擎表的默認索引類型,Memory引擎同時也支持B-Tree索引。值得一提的是,Memory引擎是支持非唯一哈希索引的,這在數(shù)據(jù)庫世界里面是比較與眾不同的。如果多個列的哈希值相同,索引會以鏈表的方式存放多個記錄指針到同一個哈希條目中。

哈希索引自身只需存儲對應(yīng)的哈希值,所以索引的結(jié)構(gòu)十分緊湊,這也讓哈希索引查找的速度非常快。從實現(xiàn)原理上,我們可以將其類比為一個巨大的 HashMap 集合。所以哈希索引也自然就有它的限制:

  • 哈希索引只包含哈希值和數(shù)據(jù)行指針,而不存儲字段值,所以不能使用索引中的值來避免讀取行,也就是不會有覆蓋索引了。不過,訪問內(nèi)存中的行的速度很快,所以大部分情況下這一點對性能的影響并不明顯。
  • 哈希索引數(shù)據(jù)并不是按照索引值順序存儲的,所以也就無法用于排序。
  • 哈希索引也不支持部分索引列匹配查找,也就是必須全值匹配,因為哈希索引始終是使用索引列的全部內(nèi)容來計算哈希值的。索引列少一點點哈希碼就不一樣,所以不可能進行部分匹配。
  • 哈希索引只支持等值比較查詢,包括=、IN()、<=>,不支持任何范圍查詢。
  • 訪問哈希索引的數(shù)據(jù)非常快,除非有很多哈希沖突。當出現(xiàn)哈希沖突的時候,存儲引擎必須遍歷鏈表中所有的行指針,逐行進行比較,直到找到所有符合條件的行。
  • 如果哈希沖突很多的話,一些索引維護操作的代價也會很高。比如在性別列上添加哈希索引,由于只存在兩種常規(guī)性別,所以哈希沖突非常嚴重,這樣的哈希索引價值也不大。

InnoDB引擎有一個特殊的功能叫做 “自適應(yīng)哈希索引(adaptive hash index)”。當InnoDB注意到某些索引值被使用得非常頻繁時,它會在內(nèi)存中基于B-Tree索引之上再創(chuàng)建一個哈希索引,這樣就讓B-Tree索引也具有哈希索引的一些優(yōu)點,比如快速的哈希查找。這是一個完全自動的、內(nèi)部的行為,用戶無法控制或者配置,不過如果有必要,完全可以關(guān)閉該功能。

② 利用自定義哈希索引提高性能

創(chuàng)建自定義哈希索引。如果存儲引擎不支持哈希索引,則可以模擬像InnoDB一樣創(chuàng)建哈希索引,這可以享受一些哈希索引的便利,例如只需要很小的索引就可以為超長的鍵創(chuàng)建索引。

思路很簡單:在B-Tree基礎(chǔ)上創(chuàng)建一個偽哈希索引。這和真正的哈希索引不是一回事,因為還是使用B-Tree進行查找,但是它使用哈希值而不是鍵本身進行索引查找。你需要做的就是在查詢的WHERE子句中手動指定使用哈希函數(shù)。

舉個例子,我們在數(shù)據(jù)庫中經(jīng)常會插入一些鏈接,這些鏈接往往很長,選擇性也一般,如果使用B-Tree來存儲URL,存儲的內(nèi)容就會很大。原來我們的查詢語句如下:

mysql> SELECT id FROM url WHERE url="http://www.mysql.com";

若刪除原來URL列上的索引,而新增一個被索引的 url_crc 字段,存放URL的哈希碼值,不僅僅能夠壓縮字符串的大小,性能也因此提升很快。

mysql> SELECT id FROM url WHERE url="http://www.mysql.com" AND url_crc=CRC32("http://www.mysql.com");

MySQL優(yōu)化器會使用這個選擇性很高而體積很小的基于 url_crc 列的索引來完成查找。即使有多個記錄有相同的索引值,查找仍然很快,只需要根據(jù)哈希值做快速的整數(shù)比較就能找到索引條目,然后一一比較返回對應(yīng)的行。而原本則是對完整的URL字符串做索引,那樣會非常慢。

當然,這樣實現(xiàn)的缺陷是需要維護哈希值。可以手動維護,也可以使用觸發(fā)器實現(xiàn)。除此以外,哈希算法的優(yōu)劣也需要注意,因為它影響著哈希索引的選擇性。索引的選擇性是指索引列中不同值的數(shù)目與表中記錄總數(shù)的比值。

III. 使用EXPLAIN

EXPLAIN工具可以確認執(zhí)行計劃是否良好,查詢是否走了合理的索引。不同版本的MySQL優(yōu)化器各有不同,一些優(yōu)化規(guī)則隨著版本的發(fā)展可能會有變化,查詢的執(zhí)行計劃可能會隨著數(shù)據(jù)的變化而變化。對于這種情況,我們可以使用EXPLAIN工具驗證自己的判斷。

使用方式

語法形式為:

explain select ·····

除此之外還有兩種變體:

explain extended select ····· show warnings

加上 extend 可以將執(zhí)行計劃反編譯成 select 語句,通過 show warnings 即可得到被MySQL優(yōu)化后的查詢語句。

另一種變體是:

explain partitions select ·····

該命令用于分區(qū)表的EXPLAIN命令。分區(qū)是將數(shù)據(jù)分段劃分在多個位置存放,可以是同一塊磁盤也可以在不同的機器。分區(qū)后,表面上還是一張表,但數(shù)據(jù)散列到多個位置了。程序讀寫的時候操作的還是大表名字,MySQL服務(wù)器自動去組織分區(qū)的數(shù)據(jù)。

我們以MySQL官方文檔中提供的示例數(shù)據(jù)庫 employees 中的 titles 為例。首先先查看它的全部索引,可以看到前三列組成主鍵索引 <emp_no, title, from_date> ,同時單獨又創(chuàng)建了一個輔助索引 <emp_no>。考慮圖片寬度,下圖的索引信息部分列被刪除。

我們進行一個查詢,并用EXPLAIN進行分析。

表格中告訴我們MySQL訪問了哪些表,以及它是如何訪問數(shù)據(jù)的。里面包含很重要的索引使用信息,據(jù)此可以判斷出索引是否需要優(yōu)化。

返回信息解讀

針對上面EXPLAIN返回的表格,我們對每一列的含義進行具體的研究。所有的信息大致可以用下面思維導(dǎo)圖表示:

MySQL EXPLAINid:表示查詢中SELECT子句或操作表的順序select_type:表示查詢中SELECT子句的類型table:表示從哪個表 (或查詢結(jié)果表) 中進行查詢type:表示MySQL在表中查找所需行的方式,也稱"訪問類型"possible_keys:指出MySQL能使用哪個索引在表中找到行,查詢涉及的字段上如果存在索引,則索引被列出,但不一定會被查詢使用key:顯示MySQL在查詢中實際使用的索引,如果沒有則為NULL。查詢中如果使用了覆蓋索引,則該索引僅出現(xiàn)在key的列表中key_len:表示經(jīng)計算得到的索引最大可能使用的字節(jié)數(shù),并非實際使用字節(jié)數(shù)。根據(jù)字節(jié)數(shù)可以推測索引最大使用長度ref:表示table中的表的連接匹配條件,即哪些列或常量被用于查找索引列上的值rows:表示MySQL根據(jù)表統(tǒng)計信息以及索引的選用情況,估算出找到目標記錄所需要讀取的行數(shù)Extra:展示那些不適合在其他列中顯示又十分重要的備注信息<dervied3> 3表示的是該查詢結(jié)果衍生自id為3的select<union1,4> 1和4表示對第1個和第4個select結(jié)果進行union操作1. SIMPLE:查詢中不包含子查詢或UNION2. PARIMARY:最外層查詢中包含任何復(fù)雜的子部分3. SUBQUERY:在select和where列表中包含的子查詢4. DERIVED (衍生):在from列表中包含的子查詢5. UNION:出現(xiàn)在UNION之后的查詢select6. UNION RESULT:從union合并的表中select1. 相同則順序由上至下;2.?子查詢id序號會遞增,id越大越優(yōu)先執(zhí)行。All:MySQL通過遍歷全表以找到匹配的行index:只遍歷索引樹找到匹配行range:索引范圍掃描,對索引的掃描開始于某一點,返回匹配值域的行ref:非唯一性索引掃描,將返回匹配某個單獨值的所有行。常用于使用非唯一索引或唯一索引的非唯一前綴進行的查找eq_ref:唯一索引掃描,對于每個索引鍵,表中只有一個記錄與之匹配。常見于主鍵索引或唯一索引掃描const:MySQL對查詢的某部分進行優(yōu)化,并轉(zhuǎn)化為一個常量。如將主鍵置于where列表中,MySQL就能將該查詢轉(zhuǎn)換為一個常量。system:是const類型的特例,當查詢的表只有一行的情況下,即可使用systemNULL:MySQL在優(yōu)化過程中分解語句,執(zhí)行時甚至不用訪問表或索引Using?index:表示相應(yīng)的select操作中使用了覆蓋索引Using?where:表示MySQL服務(wù)器在存儲引擎收到記錄后進行"后過濾"Using?temportary:表示MySQL需要使用臨時表來存儲結(jié)果集,常見于排序和分組查詢Using?filesort:文件排序,MySQL無法用索引完成的排序操作

① id

id 包含一組數(shù)字,表示查詢中執(zhí)行 select 子句或操作表的順序。如果 id 相同,則為一組,執(zhí)行順序由上至下,如果是子查詢,id 的序號會遞增,id 值越大優(yōu)先級越高,越先被執(zhí)行。

② select_type

select_type 表示查詢中每個select子句的類型,一共有如下幾種情況:

  • SIMPLE:查詢中不包含子查詢或者 UNION;
  • PRIMARY:查詢中若包含任何復(fù)雜的子部分,最外層查詢則被標記為 PRIMARY;
  • SUBQUERY:在 SELECT 或 WHERE 列表中包含了子查詢,該子查詢被標記為 SUBQUERY;
  • DERIVED:用來表示包含在 FROM 子句中的子查詢的 SELECT,MySQL會遞歸執(zhí)行并將結(jié)果放到一個臨時表中。服務(wù)器內(nèi)部稱為"派生表",因為該臨時表是從子查詢中派生出來的。
  • UNION:若第二個 SELECT 出現(xiàn)在 UNION 之后,則被標記為 UNION;
  • UNION RESULT:從 UNION 的結(jié)果表中進行的 SELECT 。

下面舉個例子,SQL語句如下

select vt1.dept_no from (select emp_no, dept_no from dept_emp where emp_no < (select emp_no from employees where emp_no = 10010)) vt1 union (select vt2.emp_no from (select emp_no from dept_manager) vt2 where emp_no < 110300);

執(zhí)行對應(yīng)的 EXPLAIN 語句查看執(zhí)行計劃。這里要關(guān)閉MySQL5.7開始的優(yōu)化器引入 derived_merge,處理 from 語句中的派生表和視圖能更好地避免不必要的物化并能夠通過條件下放產(chǎn)生更有效的執(zhí)行計劃。比如上面SQL中 union 后的一句話,子查詢 select emp_no from dept_manager 沒有條件,正常情況下需要全部遍歷輸出產(chǎn)生派生表,然后再從派生表的所有記錄中進行篩選 emp_no < 110300,這樣其實很慢,在產(chǎn)生派生表的時候就利用上篩選條件 emp_no < 110300,派生表的結(jié)果也會變小很多。

為了完整的顯示所有的查詢,我們將這種優(yōu)化先關(guān)閉。

從上圖可以看出,一共有6個查詢,基本包含了幾種常見的 select_type,按順序分析:

  • 最先執(zhí)行 id=5 的查詢,看 table 列中指明的是從 dept_manager 中查詢,可以確定是 select emp_no from dept_manager,由于該子查詢在 from 中,所以為 DERIVED
  • 然后執(zhí)行 id=4 的查詢,table 列中指明的是從 derived5 中查詢,5代表 id=5,所以確定就是 union 后面部分的查詢,外層查詢查的是派生表。由于其在 union 之后,所以該查詢標記為 UNION
  • 繼續(xù)執(zhí)行 id=3 的查詢,table 列中指明的是從 employees 中查詢,可以確定是 select emp_no from employees where emp_no = 10010,該子查詢在 where 條件中,所以是個子查詢標記為 SUBQUERY
  • id=2 的查詢 table 列中指明的是從 dept_emp 中查詢,可以確定是 select emp_no, dept_no from dept_emp where ····,同樣它的結(jié)果也是一個派生表,所以標記為 DERIVED
  • union 前的查詢?yōu)閺?fù)雜查詢,標記為 PRIMARY,其 table 列中指明的是從 derived2 中查詢;
  • 最后將 union 前后的查詢結(jié)果合并,標記為 UNION RESULT

③ type

MySQL中 explain 的 type 類型包括如下幾種,從上到下,由最差到最好。

Type含義
All全表掃描, MySQL將遍歷全表以找到匹配的行。
index索引全掃描,index 與 ALL 區(qū)別為 index 類型只遍歷索引樹。
range索引范圍掃描,對索引的掃描開始于某一點,返回匹配值域的行。顯而易見的索引范圍掃描是帶有between或者where子句里帶有<, >查詢。當MySQL使用索引去查找一系列值時,例如 IN() 和 OR 列表,也會顯示 range (范圍掃描),這種情況查詢性能往往因為結(jié)果少性能更高。
ref使用非唯一索引掃描或者唯一索引的前綴掃描,返回匹配某個單獨值的所有記錄行。
eq_ref類似 ref,區(qū)別就在使用的索引是唯一索引,對于每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用主鍵或者唯一索引作為關(guān)聯(lián)條件。
const/system當MySQL對查詢某部分進行優(yōu)化,并轉(zhuǎn)換為一個常量時,使用這些類型訪問。如將主鍵置于where 列表中,MySQL就能將該查詢轉(zhuǎn)換為一個常量。system是const類型的特例,當查詢的表只有一條記錄的情況下,即可使用system。
NULLMySQL在優(yōu)化過程中分解語句,執(zhí)行時甚至不用訪問表或索引,例如從一個索引列里選取最小值可以通過單獨索引查找完成。

④ possible_keys和key

possible_keys 指出MySQL能使用哪個索引在表中找到記錄,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢使用。

key 顯示MySQL在查詢中實際使用的索引,若沒有使用索引,顯示為 NULL。查詢中如果使用了覆蓋索引,則該索引僅出現(xiàn)在 key 的列表中。例如上面的例子中演示 type 為 index 的查詢。possible_keys 為 NULL,key 為輔助索引 emp_no。

⑤ key_len

key_len 表示索引中使用的字節(jié)數(shù),可通過該列計算查詢中使用的索引的長度。注意 key_len 顯示的值為索引字段的最大可能長度,并非實際使用長度,即 key_len 是根據(jù)表的定義計算而得,不是通過表內(nèi)檢索出的。

舉個例子,如下圖所示,我們使用 titles 表的主鍵索引——一個組合索引,分別進行減少查詢使用的索引列,emp_no 為 INT 類型,占4個字節(jié);title 為 VARCHAR 類型,50個字符,由于是utf-8字符集,每個字符3個字節(jié),所以50個字符150個字節(jié),加上2個字節(jié)存儲長度,所以占據(jù)了152字節(jié);最后 from_date 是 DATE 類型占據(jù)了3個字節(jié)。

⑥ ref

表示表的連接匹配條件,即哪些列或常量被用于查找索引列上的值。查看下面圖,表的內(nèi)外連接使用了過濾匹配條件。先看外連接,被驅(qū)動表 (a left join b 的 b) 使用了主鍵索引,驅(qū)動表作為外層循環(huán)先執(zhí)行 (id相同順序由上至下) ,需要全表掃描不走索引。對于內(nèi)連接,MySQL以數(shù)據(jù)記錄少的表作為被驅(qū)動表 (笛卡爾積的內(nèi)層循環(huán)),所以后四列都一樣。ref 的含義則是指用于索引的值來源于哪里,即內(nèi)存循環(huán)走的索引值是來源于外層循環(huán)的。

⑦ rows

表示MySQL根據(jù)表統(tǒng)計信息及索引選用情況,估算的找到所需的記錄所需要讀取的行數(shù)。

⑧ Extra

顯示那些不適合在其他列中顯示但十分重要的額外信息。可能包含四種信息,如表格所示。

Extra信息含義
Using index該值表示相應(yīng)的 select 操作中使用了覆蓋索引。
Using where表示MySQL服務(wù)器將在存儲引擎檢索行后再進行過濾。許多 where 條件里涉及索引中的列,當(并且如果)它讀取索引時,就能被存儲引擎檢驗,因此不是所有帶 where 的查詢都會顯示"Using where"。有時"Using where"的出現(xiàn)就是一個暗示:查詢可受益于不同的索引。
Using temporary表示MySQL需要使用臨時表來存儲結(jié)果集,常見于排序和分組查詢。
Using filesortMySQL中無法利用索引完成的排序操作稱為“文件排序”。

IV. 高性能索引策略

正確地創(chuàng)建和使用索引是實現(xiàn)高性能查詢的基礎(chǔ)。前面已經(jīng)著重介紹了MySQL的B-Tree索引,現(xiàn)在我們一起來看看如何真正地發(fā)揮索引的優(yōu)勢。

獨立的列

“獨立的列”是指索引列不能是表達式的一部分,也不能是函數(shù)的參數(shù)。如下面的例子:

前綴索引vs選擇性

有時候需要索引很長的字符列,這會讓索引變得大且慢。通常可以索引開始的部分字符,這樣可以大大節(jié)約索引空間,從而提高索引效率,這樣做其實是犧牲了索引的選擇性。選擇性高的索引可以讓MySQL在查找時過濾掉更多的行。唯一索引的選擇性是1,這是最好的索引選擇性,性能也是最好的。

一般情況下某個列前綴的選擇性也是足夠高的,足以滿足查詢性能。對于BLOB、TEXT或者很長的VARCHAR類型的列,必須使用前綴索引,因為MySQL不允許索引這些列的完整長度。訣竅在于要選擇足夠長的前綴以保證較高的選擇性,同時又不能太長(以便節(jié)約空間)。前綴應(yīng)該足夠長,以使得前綴索引的選擇性接近于索引整個列。

前綴長度到6時選擇性提升已經(jīng)很微小了,基本接近0.0055。當然只看平均選擇性是不夠的,也有例外的情況,需要考慮最壞情況下的選擇性。比如雖然 count(distinct left(last_name, 6)) 較大,但不代表每一種 last_name 的記錄數(shù)量是均勻分布的,可以某些 last_name 數(shù)據(jù)特別多,那么這種特定的 last_name 查詢的選擇性就很低了。

前綴索引是一種能使索引更小、更快的有效辦法,但另一方面也有其缺點:MySQL無法使用前綴索引做 ORDER BY 和 GROUP BY,也無法使用前綴索引做覆蓋掃描。

多列索引與順序

多列索引并不是給每一個列創(chuàng)建一個索引,而是多個列創(chuàng)建一個組合索引,當然多個列的排列順序也很有講究。在多個列上建立獨立的單列索引大部分情況下并不能提高MySQL的查詢性能。正確的索引列順序依賴于使用該索引的查詢,并且同時需要考慮如何更好地滿足排序和分組的需要。

在一個多列B-Tree索引中,索引列的順序意味著索引首先按照最左列進行排序,其次是第二列,等等。所以,索引可以按照升序或者降序進行掃描,以滿足精確符合列順序的 ORDER BY 、GROUP BY和 DISTINCT 等子句的查詢需求,所以多列索引的列順序至關(guān)重要。

當不需要考慮排序和分組時,將選擇性最高的列放在前面通常是很好的。這時候索引的作用只是用于優(yōu)化WHERE條件的查找。在這種情況下,這樣設(shè)計的索引確實能夠最快地過濾出需要的行,對于在WHERE子句中只使用了索引部分前綴列的查詢來說選擇性也更高。然而,性能不只是依賴于所有索引列的選擇性(整體基數(shù)),也和查詢條件的具體值有關(guān),也就是和值的分布有關(guān)。這和前面介紹的選擇前綴的長度需要考慮的地方一樣。可能需要根據(jù)那些運行頻率最高的查詢來調(diào)整索引列的順序,讓這種情況下索引的選擇性最高。

聚簇索引

聚簇索引并不是一種單獨的索引類型,而是一種數(shù)據(jù)存儲方式。具體的細節(jié)依賴于其實現(xiàn)方式,但InnoDB的聚簇索引實際上在同一個結(jié)構(gòu)中保存了B-Tree索引和數(shù)據(jù)行。

一個表只能有一個聚簇索引,因為無法同時把數(shù)據(jù)行存放在兩個不同的地方。MySQL不允許手動指定那個索引為聚簇索引,InnoDB主鍵是聚簇索引,如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引代替。如果沒有這樣的索引,InnoDB會隱式定義一個主鍵來作為聚簇索引。

聚簇主鍵可能對性能有幫助,但也可能導(dǎo)致嚴重的性能問題。

優(yōu)點主要如下

  • 可以把相關(guān)數(shù)據(jù)保存在一起。聚簇索引本身就是包含數(shù)據(jù)的,而不需要在獲取其他數(shù)據(jù)的時候再去對應(yīng)的磁盤地址進行讀取,發(fā)生磁盤IO。
  • 數(shù)據(jù)訪問更快。聚簇索引將索引和數(shù)據(jù)保存在同一個B-Tree中,因此從聚簇索引中獲取數(shù)據(jù)通常比在非聚簇索引中查找要快。
  • 使用覆蓋索引掃描的查詢可以直接使用頁節(jié)點中的主鍵值。也就是說,覆蓋索引默認包含了主鍵的字段,設(shè)計覆蓋索引的時候可以考慮不添加上主鍵字段,因為這是必然要添加的。

當然也存在缺點

  • 聚簇數(shù)據(jù)最大限度地提高了I/O密集型應(yīng)用的性能,但如果數(shù)據(jù)全部都放在內(nèi)存中,則訪問的順序就沒那么重要了,聚簇索引也就沒什么優(yōu)勢了。
  • 插入速度嚴重依賴于插入順序。按照主鍵的順序插入是加載數(shù)據(jù)到InnoDB表中速度最快的方式。但如果不是按照主鍵順序加載數(shù)據(jù),那么在加載完成后最好使用OPTIMIZE TABLE命令重新組織一下表。
  • 更新聚簇索引列的代價很高,因為會強制InnoDB將每個被更新的行移動到新的位置。基于聚簇索引的表在插入新行,或者主鍵被更新導(dǎo)致需要移動行的時候,可能面臨“頁分裂”的問題。因為B-tree索引每個節(jié)點占一頁用來存放索引,當新來的一行數(shù)據(jù)記錄的主鍵值要求必須將這一行插入到某個已滿的頁中時,存儲引擎會將該頁分裂成兩個頁面來容納該行,這就是一次頁分裂操作。頁分裂會導(dǎo)致表占用更多的磁盤空間。
  • 聚簇索引可能導(dǎo)致全表掃描變慢,尤其是行比較稀疏,或者由于頁分裂導(dǎo)致數(shù)據(jù)存儲不連續(xù)的時候。
  • 二級索引(非聚簇索引)可能比想象的要更大,因為在二級索引的葉子節(jié)點包含了引用行的主鍵列。非覆蓋索引的二級索引訪問需要二次查詢。

在介紹MyISAM和InnoDB兩種存儲引擎的時候,我們了解到兩種引擎對于數(shù)據(jù)的組織方式。MyISAM葉子節(jié)點存放了“行指針”,指向具體的數(shù)據(jù)記錄地址。MyISAM按照數(shù)據(jù)插入的順序存儲在磁盤上,對應(yīng)的地址被葉子節(jié)點記錄即可。反觀InnoDB引擎,數(shù)據(jù)本身就記錄在主鍵索引的葉子節(jié)點上,數(shù)據(jù)插入的順序完全依據(jù)主鍵在整個B-Tree樹該有的位置,如果主鍵是亂序的,那么插入數(shù)據(jù)的時候就會出現(xiàn)樹的左邊插一個,右邊插一個,這邊插一個,那邊插一個的現(xiàn)象。這么做有什么隱患呢,首先插入時間長,其次占據(jù)空間可能更大,碎片化嚴重。具體如下:

  • 寫入的目標頁可能已經(jīng)刷到磁盤上并從緩存中移除,或者是還沒有被加載到緩存中,InnoDB在插入之前不得不先找到并從磁盤讀取目標頁到內(nèi)存中。這將導(dǎo)致大量的隨機I/O。
  • 因為寫入是亂序的,InnoDB不得不頻繁地做頁分裂操作,以便為新的行分配空間。頁分裂會導(dǎo)致移動大量數(shù)據(jù),一次插入最少需要修改三個頁而不是一個頁。
  • 由于頻繁的頁分裂,頁會變得稀疏并被不規(guī)則地填充,所以最終數(shù)據(jù)會有碎片。

那么,如何利用好InnoDB主鍵順序插入數(shù)據(jù)的特點呢?

那就是有序的主鍵,比如自增長列。因為主鍵的值是順序的,所以InnoDB把每一條記錄都存儲在上一條記錄的后面。當達到頁的最大填充因子時(InnoDB默認的最大填充因子是頁大小的15/16,留出部分空間用于以后修改),下一條記錄就會寫入新的頁中。一旦數(shù)據(jù)按照這種順序的方式加載,主鍵頁就會近似于被順序的記錄填滿,這也正是所期望的結(jié)果。

覆蓋索引

使用覆蓋索引的好處在于:

  • 索引字段數(shù)目通常遠小于數(shù)據(jù)記錄的所有字段數(shù)目,所以如果只需要讀取索引,那MySQL就可以極大地減少數(shù)據(jù)訪問量。這對緩存的負載非常重要,因為這種情況下響應(yīng)時間大部分花費在數(shù)據(jù)拷貝上。覆蓋索引對于I/O密集型的應(yīng)用也有幫助,因為索引比數(shù)據(jù)更小,更容易全部放入內(nèi)存中(這對于MyISAM尤其正確,因為MyISAM能壓縮索引以變得更小)。
  • 由于InnoDB的聚簇索引,覆蓋索引對InnoDB表特別有用。InnoDB的二級索引在葉子節(jié)點中保存了行的主鍵值,所以如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢。

不是所有類型的索引都可以成為覆蓋索引。覆蓋索引必須要存儲索引列的值,而哈希索引、空間索引和全文索引等都不存儲索引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引。

InnoDB的二級索引的葉子節(jié)點都包含了主鍵的值,這意味著InnoDB的二級索引可以有效地利用這些“額外”的主鍵列來覆蓋查詢。換句話說,二級索引查詢主鍵也是覆蓋索引。

利用索引掃描進行排序

通過B-Tree索引的實現(xiàn)原理,我們可以知道 ORDER BY 排序也是可以從索引獲益的。ORDER BY 子句和查找型查詢的限制是一樣的:需要滿足索引的最左前綴的要求;否則,MySQL都需要執(zhí)行排序操作,而無法利用索引進行排序。

當然,有一種情況下 ORDER BY 子句可以不滿足索引的最左前綴的要求,就是前導(dǎo)列為常量的時候。如果 WHERE 子句或者 JOIN 子句中對這些列指定了常量,就可以“彌補”索引的不足。

如下圖舉出一些例子。

冗余重復(fù)不使用的索引

MySQL允許在相同列上創(chuàng)建多個索引,無論是有意的還是無意的。MySQL需要單獨維護重復(fù)的索引,并且優(yōu)化器在優(yōu)化查詢的時候也需要逐個地進行考慮,這會影響性能。

重復(fù)索引是指在相同的列上按照相同的順序創(chuàng)建的相同類型的索引。應(yīng)該避免這樣創(chuàng)建重復(fù)索引,發(fā)現(xiàn)以后也應(yīng)該立即移除。

冗余索引和重復(fù)索引有一些不同。如果創(chuàng)建了索引(A,B),再創(chuàng)建索引(A)就是冗余索引,因為這只是前一個索引的前綴索引。因此索引(A,B)也可以當作索引(A)來使用(這種冗余只是對B-Tree索引來說的)。但是如果再創(chuàng)建索引(B,A),則不是冗余索引,索引(B)也不是,因為B不是索引(A,B)的最左前綴列。

除了冗余索引和重復(fù)索引,可能還會有一些服務(wù)器永遠不用的索引。這樣的索引完全是累贅,建議考慮刪除。

V. 總結(jié)

在MySQL中,大多數(shù)情況下都會使用B-Tree索引。其他類型的索引大多只適用于特殊的目的。如果在合適的場景中使用索引,將大大提高查詢的響應(yīng)時間。本章將不再介紹更多這方面的內(nèi)容了,最后值得總的回顧一下這些特性以及如何使用B-Tree索引。

在選擇索引和編寫利用這些索引的查詢時,有如下三個原則始終需要記住:

  • 單行訪問是很慢的。特別是在機械硬盤存儲中(SSD的隨機I/O要快很多,不過這一點仍然成立)。如果服務(wù)器從存儲中讀取一個數(shù)據(jù)塊只是為了獲取其中一行,那么就浪費了很多工作。最好讀取的塊中能包含盡可能多所需要的行。使用索引可以創(chuàng)建位置引用以提升效率。
  • 按順序訪問范圍數(shù)據(jù)是很快的。這有兩個原因。第一,順序I/O不需要多次磁盤尋道,所以比隨機I/O要快很多,特別是對機械硬盤。第二,如果服務(wù)器能夠按需要順序讀取數(shù)據(jù),那么就不再需要額外的排序操作,并且GROUP BY 查詢也無須再做排序和將行按組進行聚合計算了。
  • 索引覆蓋查詢是很快的。如果一個索引包含了查詢需要的所有列,那么存儲引擎就不需要再回表查找行。這避免了大量的單行訪問。

除了這些,對于 EXPLAIN 的使用也是至關(guān)重要的。

參考閱讀

  • 什么是CPU密集型、IO密集型?
  • 淺談算法和數(shù)據(jù)結(jié)構(gòu): 十 平衡查找樹之B樹
  • MySQL索引背后的數(shù)據(jù)結(jié)構(gòu)及算法原理
  • 《MySQL DBA修煉之道》
  • 《高性能MySQL》

總結(jié)

以上是生活随笔為你收集整理的MySQL——索引与EXPLAIN的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

国产破处精品 | 久久久久国产a免费观看rela | 一区二区亚洲精品 | 久久久精品午夜 | 伊人六月 | 欧美日韩午夜 | 97精品国产aⅴ | 国产中文字幕一区 | 国产99精品| 操操日日| 亚洲综合视频在线观看 | 久久激情综合 | 韩国av不卡 | 国产综合在线视频 | 五月婷在线 | 国产精品久久久久9999 | 久久人人插 | 国产精品乱码久久 | 超薄丝袜一二三区 | 午夜久久影院 | av黄在线播放 | 在线视频 精品 | 日韩手机在线观看 | 黄色免费国产 | 国产成人精品999在线观看 | 天天色天天干天天 | 欧美黄色成人 | 不卡av免费在线观看 | 日韩一区精品 | 狠狠色丁香婷婷综合视频 | 免费网站黄 | 人人插人人射 | 人人玩人人弄 | 在线观看亚洲a | 久久精品国产亚洲aⅴ | 天天撸夜夜操 | 国产黄色播放 | 久久精品—区二区三区 | 91福利视频在线 | 97偷拍视频 | 91最新国产| 亚洲人成人在线 | 亚洲高清视频一区二区三区 | 国产高清精 | 97狠狠干 | 久久精久久精 | 国产美女免费观看 | 欧洲性视频 | 香蕉国产91 | 黄色视屏免费在线观看 | 瑞典xxxx性hd极品 | 国产日韩中文字幕 | 免费人成在线观看网站 | 18久久久久久 | 国产日韩精品一区二区三区 | 国产黄a三级三级三级三级三级 | www.久艹| 久久这里只有精品视频首页 | 成 人 黄 色 片 在线播放 | 91视频在线播放视频 | 蜜臀av性久久久久蜜臀aⅴ四虎 | 成人免费观看完整版电影 | 91手机电视 | 免费高清在线观看电视网站 | 探花视频免费在线观看 | 精品国产伦一区二区三区免费 | 久久女教师 | 亚洲一区黄色 | 日韩在线中文字幕视频 | 六月丁香社区 | 国产人成一区二区三区影院 | 一本一道久久a久久综合蜜桃 | 97人人爽| 综合激情伊人 | 久久电影网站中文字幕 | 久久国产热视频 | 亚洲免费在线观看视频 | 成人动漫一区二区三区 | 日韩精品播放 | 久久亚洲精品国产亚洲老地址 | 亚洲人成精品久久久久 | 欧美日韩18 | 成人小视频在线免费观看 | 手机av在线不卡 | 久久亚洲私人国产精品va | 久久a国产 | 91精品久 | 亚洲精品国产综合久久 | 99精品视频免费观看 | 天天色棕合合合合合合 | 久久免费资源 | 国产一区视频在线观看免费 | 精品久久久久久国产91 | 狠狠色丁香 | 久久久久久国产精品免费 | 操综合| av大全在线免费观看 | 婷婷av综合 | 91九色porny蝌蚪视频 | 天天色成人网 | 狠狠躁日日躁狂躁夜夜躁 | 久久神马影院 | 国产精品一区二区电影 | 丁香六月久久综合狠狠色 | 女人久久久久 | 亚洲特级毛片 | 久久国产一区 | 亚洲精品视频第一页 | 午夜在线免费观看视频 | 国产va在线 | 四虎国产永久在线精品 | 日韩av电影国产 | 天天天天爱天天躁 | 久久草在线精品 | 婷婷在线色 | 中文字幕 影院 | 日本视频高清 | 人人爽人人看 | 久久国产高清视频 | 久久久久久久网 | 免费观看成年人视频 | 麻豆国产精品va在线观看不卡 | 亚洲精品免费播放 | 亚洲蜜桃在线 | 婷婷国产视频 | 成人一级影视 | 久久婷婷一区二区三区 | 91污视频在线 | 中文高清av| 一区二区三区日韩精品 | 久久精品99 | 久久视奸| 久草亚洲视频 | 特级aaa毛片 | 97激情影院 | 天堂av免费看 | 亚洲伊人网在线观看 | 丁香婷婷激情啪啪 | 色老板在线视频 | 日韩高清不卡在线 | 麻豆影视在线观看 | 在线免费国产 | 在线天堂v| 欧美巨大| 天天射网 | 97在线视频免费看 | 欧美一级久久久 | 激情在线免费视频 | 国产精华国产精品 | 玖玖精品视频 | 永久免费精品视频 | 久久试看 | 狠狠狠色丁香综合久久天下网 | 精品国产一区二 | 久久艹影院 | 四虎在线观看视频 | 精品久久久免费视频 | 亚洲精品观看 | 国产精品视频不卡 | 日韩网站在线免费观看 | 韩国av电影网 | 亚洲无吗av | 欧美久久久久久久久 | 久久综合网色—综合色88 | 一区二区三区日韩在线 | 激情欧美丁香 | a亚洲视频 | 国产精品美女视频网站 | 日韩视频三区 | 六月丁香在线视频 | 一区二区三区韩国免费中文网站 | 欧洲性视频 | 久草在线视频首页 | 97在线观看免费观看高清 | 伊人天堂av| 日日夜夜精品视频天天综合网 | 久久不卡国产精品一区二区 | 国产黄色精品 | 亚洲高清色综合 | 亚洲网久久 | 色婷婷综合久久久 | 日韩欧美在线中文字幕 | 日韩精品高清视频 | 三级av在线 | 五月婷婷在线观看 | 免费黄色在线播放 | 国产精品欧美久久久久无广告 | 久草免费在线视频观看 | 丁香六月婷婷开心婷婷网 | 狠狠狠色丁香综合久久天下网 | 日韩免费观看视频 | 久久你懂的| 插久久 | 色88久久 | 国产欧美在线一区 | 国产不卡网站 | 欧美一二三区在线播放 | 久久99久久久久久 | 欧美精品网站 | 久久人人爽 | 久久久久亚洲精品成人网小说 | 亚洲综合色视频在线观看 | 97视频网址 | 精品国产区 | 青青啪 | 久久久人| 综合网色 | 免费一级日韩欧美性大片 | 午夜精品久久久久久久久久久久久久 | 91亚洲精品国偷拍自产在线观看 | 欧美日本在线观看视频 | 色在线国产 | 婷婷成人综合 | 成人免费xxxxxx视频 | 日本成址在线观看 | 九九热在线精品视频 | 丰满少妇在线观看网站 | 国产美女永久免费 | 色综合久久久久久久久五月 | 日韩大片在线播放 | 日韩欧美视频免费在线观看 | 99精品一区二区三区 | www.综合网.com| 五月天激情视频 | 日韩av中文字幕在线 | 久久这里只有精品视频首页 | 最新午夜电影 | 精品一区 在线 | 国产成人av | 一级黄色大片 | 成 人 黄 色 免费播放 | 久在线观看视频 | 久久久久久久影院 | 高清av免费一区中文字幕 | 久久久久久久久久久国产精品 | 欧美精品在线一区二区 | 色人久久 | 色偷偷网站视频 | 国产精品99久久久精品 | 免费高清在线观看电视网站 | 96av在线视频 | 中文字幕在线观看完整版电影 | 日本最新一区二区三区 | 五月花婷婷 | 欧美午夜激情网 | 亚洲精品www. | 韩国一区在线 | 一区二区三区在线播放 | 久久精品影片 | 欧美黑人性爽 | 亚洲爽爽网 | 中文字幕乱码亚洲精品一区 | www.国产高清| 五月天中文字幕mv在线 | 六月色丁香 | 狠狠躁夜夜躁人人爽超碰91 | 欧美一级淫片videoshd | 欧美一级片在线免费观看 | 在线观看久草 | 波多野结衣精品 | 成人97视频 | 国产精品99久久久精品 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 天堂在线免费视频 | 国产精品99久久久久人中文网介绍 | 天天添夜夜操 | 免费在线观看的av网站 | 国产一区二区免费看 | 人人插人人草 | 成人蜜桃 | 在线观看视频黄色 | 日韩中文字幕在线看 | 婷婷亚洲五月 | 91日韩精品视频 | 国产精品亚洲片在线播放 | 狠狠操夜夜操 | 久久福利剧场 | 欧美成人区| 国产精品久久久久久久电影 | 综合网婷婷 | 国产又粗又猛又黄 | 中文字幕人成一区 | 在线影院中文字幕 | 97人人艹| 日本午夜在线观看 | 99亚洲国产 | 日本 在线 视频 中文 有码 | 日韩av一区二区三区在线观看 | 九七在线视频 | 97电院网手机版 | 中文字幕在线看视频 | av大片网站| 很黄很污的视频网站 | av黄色免费在线观看 | 国产视频不卡一区 | 国产麻豆果冻传媒在线观看 | 深爱激情婷婷网 | 亚洲天堂激情 | 国产一级片在线播放 | 久久综合五月婷婷 | 亚洲欧美综合精品久久成人 | 日日摸日日 | 一二三区视频在线 | www欧美日韩 | 91最新视频| 日日夜精品 | 中文字幕成人 | 色综合久久中文综合久久牛 | 久久99国产综合精品 | 久久av免费电影 | 午夜久久影院 | 国产高清视频免费最新在线 | 国产一区在线免费观看视频 | 在线观看岛国av | 一区二区三区四区不卡 | 超碰在线97国产 | 日韩精品一区在线观看 | 国产精品视频永久免费播放 | 久久精品欧美 | 一本一本久久a久久精品牛牛影视 | 精品国产一区二区三区免费 | 久久免费视频5 | 日韩午夜视频在线观看 | 天天干com | 日日干夜夜草 | 最近中文字幕视频网 | a级一a一级在线观看 | 国产精品久久久久久久久免费看 | 探花在线观看 | 999久久久久 | 性色va| 亚洲视频专区在线 | 欧美孕交vivoestv另类 | 97国产小视频| 国产123区在线观看 国产精品麻豆91 | 黄色三级免费 | 99热这里有精品 | 911亚洲精品第一 | 精品黄色片 | 中文字幕色在线 | 96精品高清视频在线观看软件特色 | 99久久精品免费看国产免费软件 | 在线观看成人小视频 | 在线影院 国内精品 | 日韩精品一区二区三区免费观看视频 | 精品福利av| 99久久精品无码一区二区毛片 | 亚洲免费黄色 | 成人午夜在线电影 | 色综合天天狠狠 | 国产91欧美 | 99视频在线 | 美女免费视频一区二区 | 精品自拍av | 一区二区理论片 | 久久视频国产精品免费视频在线 | 91av在线视频播放 | 福利av影院 | 五月天六月婷婷 | 国产精品欧美日韩在线观看 | 久久亚洲综合色 | 免费观看成人网 | 成片免费观看视频999 | 国产成人精品久久久久 | 青青草久草在线 | 日韩在线视频播放 | 国产精品美女久久久免费 | 狠狠色2019综合网 | 欧美另类z0zx | 五月婷婷视频在线 | 久久一区二区免费视频 | 国产精品久久久久久久免费 | 九九精品视频在线观看 | 三级av在线| 精品国产伦一区二区三区观看体验 | 久久久精品国产一区二区电影四季 | 久久婷婷国产色一区二区三区 | 欧美9999| 色综合激情久久 | 国产69精品久久久久久久久久 | 日韩电影中文字幕在线观看 | 日日干夜夜爱 | 欧美一级久久久久 | 在线观看资源 | 久久国产乱 | 91完整版观看 | 亚洲五月婷 | 国产精品美女999 | 国产正在播放 | 国产精品99久久免费观看 | 欧美a级免费视频 | 日韩美女免费线视频 | 99re国产视频 | 久久久久黄 | 500部大龄熟乱视频使用方法 | 色播五月激情综合网 | 在线电影日韩 | 久久婷婷亚洲 | 婷婷丁香激情五月 | 久久久免费看视频 | 成人免费视频网 | 久久免费精品 | 国产精品第54页 | 视频在线亚洲 | 天天干天天干天天干天天干天天干天天干 | 岛国大片免费视频 | 狠狠躁夜夜a产精品视频 | 天天色天天操天天爽 | 亚洲高清精品在线 | 天天综合在线观看 | 五月天com| 久久高清免费 | 中文字幕日韩电影 | 4438全国亚洲精品在线观看视频 | 欧美日韩免费一区二区 | 热re99久久精品国产66热 | 国产精品精品 | 九色最新网址 | 国产明星视频三级a三级点| 天天爽天天搞 | 国产黄色在线观看 | 中文字幕日韩有码 | 夜夜夜夜夜夜操 | 天天视频色 | 国内精品久久影院 | 中文字幕日本在线观看 | 日本精品视频一区二区 | 久久国产日韩 | 日韩 在线观看 | sesese图片 | 国产黄色大片免费看 | 亚洲国产偷| av黄色av| 91在线精品播放 | 久久男人视频 | 国产精品99久久久久久人免费 | 五月天免费网站 | 色婷婷久久一区二区 | 黄色三级视频片 | 国产在线精品国自产拍影院 | 97网在线观看 | 国产精品永久在线 | 97精品国产97久久久久久粉红 | 亚洲涩综合 | 久久婷亚洲五月一区天天躁 | 国外成人在线视频网站 | 亚洲伦理精品 | 中文字幕在线播放第一页 | 日韩欧美xxxx | av久久久| 成人av免费在线 | 国产精品高潮呻吟久久av无 | 日日狠狠 | 在线天堂中文在线资源网 | 9999精品| 国产理论影院 | 国产91精品看黄网站 | 亚洲视频免费在线 | 久久久久久国产精品亚洲78 | 天天干 夜夜操 | 久久国产精品第一页 | 国产中文字幕在线看 | 国产精品久久一区二区三区, | 久99久久 | 911久久香蕉国产线看观看 | 欧美少妇18p| 久久久久在线 | 黄色一级大片在线免费看国产一 | 国产精品密入口果冻 | 在线免费视频一区 | 一区二区三区手机在线观看 | 日本高清免费中文字幕 | 国产成人精品亚洲日本在线观看 | 久久精品免费电影 | 国产中文字幕免费 | 亚洲va欧美va| 国产va精品免费观看 | 国产精品区一区 | 成人a级网站 | 国产视频18 | 亚洲天天综合网 | 久久人91精品久久久久久不卡 | 456免费视频 | 亚洲三级视频 | 黄色大片视频网站 | 日本韩国精品在线 | 欧美日产一区 | 国内丰满少妇猛烈精品播放 | 99久久精品久久久久久清纯 | 嫩嫩影院理论片 | 三级在线视频观看 | 久久天 | 国产精品二区在线观看 | 美女网站视频一区 | 色综合久久久久网 | 天天综合网天天 | 亚洲激情六月 | 国产精品美女久久久久久久网站 | 国产精品二区在线观看 | 97av在线视频免费播放 | 欧美aa一级片 | 午夜久久影视 | 久久久www成人免费毛片 | 日韩最新av| 九九免费精品视频 | 丁香六月国产 | 久久tv | 手机av观看| 国产精华国产精品 | 日韩av伦理片| 国产精品久久久久久久久久尿 | 日韩高清国产精品 | 亚洲综合色丁香婷婷六月图片 | 久久一本综合 | 日韩特黄一级欧美毛片特黄 | 成人av电影免费在线观看 | 五月天激情综合网 | 国产日产精品一区二区三区四区 | av成人免费 | 欧美一区二区精美视频 | av亚洲产国偷v产偷v自拍小说 | 日韩精品在线观看av | 青草视频在线免费 | 久久综合操 | 在线天堂8√ | 黄色美女免费网站 | 久久高清视频免费 | 成年人黄色免费网站 | 久久人人爽人人片av | 久久精品99国产 | 日韩在线免费 | 91精品日韩 | 成人黄色在线看 | 色5月婷婷 | 99国产视频 | 黄色aaaaa| 丰满少妇在线观看资源站 | 国产一区二区三区在线免费观看 | 久久成人国产精品免费软件 | 色婷婷亚洲婷婷 | 黄色免费网站大全 | 超碰在线公开 | 最近中文字幕完整视频高清1 | 97天天干| 中文字幕av在线电影 | 日韩电影在线一区二区 | 国产一区二区三区免费在线 | 美女久久久久久 | 国产网站在线免费观看 | 日韩精品一区二区三区第95 | 久久激情五月婷婷 | 成人av网站在线播放 | 国产精品入口麻豆www | 91av原创 | 亚洲最快最全在线视频 | 亚洲视频在线观看网站 | 久久综合久久综合九色 | 在线日本看片免费人成视久网 | 精品自拍av| 免费手机黄色网址 | 日韩网站在线观看 | 香蕉久久国产 | 黄色av电影免费观看 | 亚洲成人xxx| 韩日精品视频 | 国产免费作爱视频 | 色综合天天做天天爱 | 999日韩| 国产91九色视频 | 青草草在线视频 | 久热香蕉视频 | 粉嫩av一区二区三区入口 | 婷婷综合导航 | 亚洲毛片一区二区三区 | 国产二区免费视频 | 日韩av电影手机在线观看 | 国产精品2020 | 国产精品h在线观看 | 人人草人人做 | 免费看三级黄色片 | 偷拍精偷拍精品欧洲亚洲网站 | 久操97 | 国产最新视频在线观看 | 91精品国产高清自在线观看 | 国产综合小视频 | 久草国产在线 | h网站免费在线观看 | 久久天天躁夜夜躁狠狠躁2022 | 欧美日韩精品免费观看视频 | 国产原创在线视频 | 玖玖综合网 | 久久久久北条麻妃免费看 | 日韩久久精品一区二区三区下载 | 欧美a级在线免费观看 | 在线看的av网站 | av日韩精品| 91精品国产自产在线观看永久 | 中文字幕日本特黄aa毛片 | 欧美巨大荫蒂茸毛毛人妖 | 成人小视频在线免费观看 | 一级黄色在线视频 | 国产免费不卡av | 欧美日韩免费一区二区三区 | 亚洲日本国产精品 | 久久免费中文视频 | 中文字幕乱码一区二区 | 狠狠狠操 | 天天爱天天草 | 亚洲精品视频免费 | 国产精品毛片一区视频播 | 中文字幕在线观看视频一区二区三区 | 免费手机黄色网址 | 中文字幕精品www乱入免费视频 | 人人玩人人添人人澡97 | 蜜臀久久99精品久久久无需会员 | 久久久久免费看 | 天天看天天干天天操 | 依人成人综合网 | 国产在线观看免费观看 | 国产精品999久久久 久产久精国产品 | 亚洲日韩中文字幕 | 日韩欧美国产免费播放 | 色婷婷综合激情 | 亚洲精品97 | 亚洲精品资源在线观看 | 91精品国产自产在线观看 | 91精品导航 | 久久久久久片 | 欧美日韩成人一区 | 国内亚洲精品 | 午夜视频在线观看欧美 | 99精品久久精品一区二区 | 久久情网 | 成人一区二区三区在线观看 | 国产成人一区二区三区影院在线 | 高清av影院 | 狠狠干中文字幕 | www.com久久 | 久久人人爽人人爽人人片 | 免费亚洲视频 | 人人爽人人射 | 日韩精品一区二区三区水蜜桃 | 伊人网综合在线观看 | 国产一区二区精 | 欧美成人理伦片 | 99精品国产视频 | 欧美日韩一区二区三区在线观看视频 | 欧美一区二区三区免费观看 | 97福利| 在线观看色网 | 福利片视频区 | 色婷婷av国产精品 | 99一区二区三区 | 欧美天天干 | 91精品国产福利在线观看 | 91字幕| 免费男女羞羞的视频网站中文字幕 | 亚洲免费观看视频 | 久久开心激情 | 日日碰夜夜爽 | www.国产精品 | 在线国产一区 | 久久综合九色综合欧美狠狠 | 精品久久在线 | 欧美成人999 | 日韩专区在线 | 最近中文字幕 | 亚洲免费精品一区二区 | 免费黄色在线网址 | 中文一区二区三区在线观看 | 人人干在线观看 | 成人久久久久久久久 | 欧美成人h版电影 | 欧美一区二区三区在线 | 狠狠色丁婷婷日日 | 六月婷婷网 | 国产精品免费一区二区三区 | 国模视频一区二区三区 | 亚洲欧美激情插 | 五月天色网站 | 精品福利在线观看 | 久久精品国产一区二区 | 国产69精品久久99不卡的观看体验 | 国内久久久久久 | 久久视频这里有久久精品视频11 | 国产露脸91国语对白 | 国产一区私人高清影院 | 久久免费毛片视频 | 日韩欧美综合在线视频 | 99精品免费观看 | 精品国产一区二 | 欧美做受xxx | 夜色资源站国产www在线视频 | 99热国产在线观看 | 在线视频国产区 | 亚洲精品美女在线观看播放 | 国产黄在线 | 2024国产精品视频 | 99在线免费视频观看 | 伊人五月天综合 | 日日夜色| 91欧美国产 | 精品久久久久久久久亚洲 | 成人黄色片免费 | 成人在线你懂得 | 午夜国产福利在线观看 | 麻花豆传媒mv在线观看 | 久久精品久久综合 | 一级片黄色片网站 | 天天色综合久久 | 国产精品久久久久久久久岛 | 日韩精品免费一区二区 | 国产丝袜网站 | 久久精品日韩 | 欧美成人手机版 | 91精品少妇偷拍99 | 99精品国产兔费观看久久99 | 欧美男同视频网站 | 高清精品久久 | 69热国产视频 | 麻豆观看 | www国产亚洲精品 | 久久黄网站 | 亚洲精品字幕 | 国产成人精品一区二区三区福利 | 91av手机在线观看 | 日本精品一区二区三区在线观看 | 欧美日韩一二三四区 | 综合激情av| 激情在线网址 | 五月天亚洲婷婷 | 最新极品jizzhd欧美 | 欧美精品做受xxx性少妇 | 亚洲午夜精品福利 | 黄污网站在线观看 | 亚洲精品在线视频 | 午夜在线日韩 | 亚洲在线视频免费 | 91看片在线播放 | 国产精品一区二区av影院萌芽 | 91在线看黄| 婷婷播播网 | 久久视频二区 | 91午夜精品 | 片网站 | 99在线热播精品免费 | 美女福利视频在线 | 91亚洲网 | 中文av影院| 69视频永久免费观看 | 国产淫片免费看 | 成人黄色影片在线 | 麻豆成人在线观看 | 久久久免费精品国产一区二区 | 黄色在线观看www | 久久激情五月丁香伊人 | 五月情婷婷| 国内精品久久久久影院男同志 | 色吊丝av中文字幕 | 黄色大片国产 | 在线观看亚洲成人 | 日韩免费一二三区 | 天天色宗合 | 美女国内精品自产拍在线播放 | 中国一级特黄毛片大片久久 | 黄色精品一区 | 欧美日韩国产综合网 | 天堂va在线高清一区 | 99热官网 | 亚洲在线网址 | www.天天干.com | 成人精品影视 | 日韩色av色资源 | 一区二区三区免费在线观看视频 | 91黄在线看 | 成人在线视频免费观看 | 欧美黄污视频 | 在线观看视频中文字幕 | 日韩在线网址 | 精品久久1| 久久精品免费观看 | 日韩欧美在线一区 | 午夜久久精品 | 9热精品 | 黄色免费网站 | 久久久久国| 99久久99视频只有精品 | 久久久精品免费观看 | 日韩理论片在线 | 欧美尹人 | 久草a视频| 91网在线看 | 97国产大学生情侣酒店的特点 | 精品中文字幕视频 | 亚洲国产人午在线一二区 | 久久99久久99免费视频 | 国产成人综 | 欧美日韩国内在线 | 日韩美女一级片 | 在线免费av网 | 国产精品黄色影片导航在线观看 | 天天色天天射天天操 | 欧美无极色 | 日韩精品免费在线视频 | 岛国av在线免费 | 97视频久久久 | 亚洲国产成人在线 | 成人禁用看黄a在线 | 国产手机av在线 | 亚洲va男人天堂 | 日韩欧美有码在线 | 91成人精品 | 久久精品网站免费观看 | 成人免费视频观看 | 国产小视频在线 | 国产精品午夜久久久久久99热 | 九七视频在线观看 | 91在线播放国产 | av丝袜制服 | 日韩精品一区二区在线观看视频 | 久操视频在线免费看 | 一区二区三区四区在线 | av黄色在线观看 | 碰碰影院| 欧美少妇xxxxxx| 99久久精品国产毛片 | 九九热免费视频在线观看 | 久久艹国产视频 | 永久免费精品视频网站 | 国产对白av | 亚洲综合在线五月 | 久久精品国产精品亚洲 | 69绿帽绿奴3pvideos | 久艹视频在线免费观看 | 久久久久免费精品国产 | 在线91视频 | 国内成人精品2018免费看 | 91免费视频网站在线观看 | 亚洲高清视频在线观看免费 | www.亚洲在线| 六月激情久久 | 99视频久久 | 欧美日韩国产精品一区二区 | 五月天激情开心 | 人人澡人人添人人爽一区二区 | 九九久 | 超碰在线97观看 | 国产精品一区二区在线观看 | 国产在线观看91 | 成人av动漫在线 | 久久一区精品 | 欧美午夜理伦三级在线观看 | 午夜久久精品 | 国产高清精| 国产亚洲高清视频 | 99热精品久久 | 日韩天天干| 777视频在线观看 | 久久99精品久久久久久三级 | 久久精品牌麻豆国产大山 | 免费人成在线观看网站 | 日韩在线视频网址 | 99国内精品 | 成人午夜电影久久影院 | 日韩激情中文字幕 | 国产精品永久久久久久久www | 国产99久久久国产精品免费看 | 2019中文字幕第一页 | 在线观看一区二区精品 | 日韩综合在线观看 | 福利一区在线视频 | 免费在线看v | 在线免费观看视频 | 91久久久久久久 | 日韩av一区二区三区 | 91新人在线观看 | 国产免费xvideos视频入口 | 五月开心六月婷婷 | 园产精品久久久久久久7电影 | 99中文字幕视频 | 天天插天天爽 | 亚洲成人精品av | 黄色片软件网站 | 国产录像在线观看 | 麻豆一区在线观看 | 日日骑| 国产精品大尺度 | 亚洲激情婷婷 | 国产91在线观看 | 中文字幕在线观看第二页 | 国产福利网站 | 黄色软件视频大全免费下载 | 国产午夜精品一区二区三区 | 国产人成免费视频 | 久久久久久高潮国产精品视 | 中文字幕在线一区二区三区 | 国产精品成人一区二区 | 午夜精品久久久久 | 久久久首页 | 中文字幕国产精品一区二区 | 国产黄免费在线观看 | 久久久久国产精品免费免费搜索 | 日韩一区二区三区免费视频 | 久久99在线| 久青草电影 | 久久激情小说 | 欧美一区在线观看视频 | 国产真实精品久久二三区 | 久久久精品 一区二区三区 国产99视频在线观看 | www.狠狠| av电影在线免费观看 | 国内精品久久久久久久久久清纯 | 日韩在线免费视频 | 国产精品美女久久久久久久网站 | 欧美精品久久99 | 欧美国产精品久久久久久免费 | 日本女人在线观看 | 美女国产网站 | 久久经典视频 | 亚洲国产精品成人女人久久 | 国产老熟| 99精品毛片 | 国产剧情av在线播放 | 国产成人在线看 | 中文字幕在线日 | 久久男女视频 | 1024手机在线看 | 一区二区三区日韩精品 | 久久不卡视频 | 在线观看 亚洲 | 成人在线观看资源 | 狠狠操狠狠 | 国产特级毛片 | 久久久精品免费观看 | 五月激情五月激情 | 国产亚洲精品久久久久久移动网络 | 91精品国产麻豆 | 99热这里只有精品在线观看 | 99精品国产免费久久 | 久久精品国产一区二区三 | 国产成人精品福利 | 亚洲永久精品国产 | av免费在线观看网站 | 日韩电影一区二区在线 | 24小时日本在线www免费的 | 91看片在线 | 又大又硬又黄又爽视频在线观看 | 欧美日韩中文字幕视频 | 国产一级特黄毛片在线毛片 | 麻豆免费在线播放 | 国产xx在线| 久久人人97超碰国产公开结果 | 久久久在线视频 | 久久久久欧美精品 | 久久在线一区 | 99热这里只有精品在线观看 | 九九久| www.天天干.com | 狠狠躁天天躁 | 久久精品99国产精品亚洲最刺激 | 日本少妇久久久 | 亚洲精品视频久久 | 久久久久国产免费免费 | 免费观看的av | 大胆欧美gogo免费视频一二区 | 国产视频2区 | 一级黄色片在线 | 91精品久久久久久综合乱菊 | 国产精品美女久久久免费 | 日韩中文字幕免费在线播放 | 国产另类xxxxhd高清 | 一区二区精品视频 | 91免费在线 | 日韩视频一区二区三区 | 日韩网页 | 欧美男同网站 | 日韩电影在线观看一区二区 | 国产一区二区三区在线免费观看 | 久久国产精品一国产精品 | 91桃色免费视频 | 亚洲麻豆精品 | 97人人网| 91在线九色 | 97免费在线视频 | 一区二区三区韩国免费中文网站 | 久久夜色精品国产欧美一区麻豆 | 午夜视频在线瓜伦 | 狠狠干天天操 | 激情综合电影网 | 中文字幕在线视频精品 | 精品一区在线看 | 视频精品一区二区三区 | 国产免费黄视频在线观看 | 高清免费在线视频 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 亚洲日韩精品欧美一区二区 | 最近中文字幕免费大全 | 天天干天天操天天爱 |