1. 程式人生 > >MySQL索引與優化

MySQL索引與優化

概念

索引儲存在記憶體中,為伺服器儲存引擎為了快速找到記錄的一種資料結構。

基本操作

為資料表新增索引:

ALTER TABLE table_name ADD INDEX index_name (column_list) //普通索引

ALTER TABLE table_name ADD UNIQUE (column_list) //唯一性索引,設定後,不允許插入重複值

ALTER TABLE table_name ADD PRIMARY KEY (column_list) //唯一索引,通常用於自增主鍵。

刪除索引

DROP INDEX index_name ON talbe_name

ALTER TABLE table_name DROP INDEX index_name

ALTER TABLE table_name DROP PRIMARY KEY

檢視索引

SHOW INDEX FROM tblname;

SHOW KEYS FROM tblname;

優缺點及使用場景

減少表的檢索行數,提高查詢效率

建立唯一索引或者主鍵索引,保證資料欄位的唯一性

檢索時有分組和排序需求時,減少伺服器排序的時間

缺點:

建立和維護索引需要消耗時間及記憶體,隨著資料的增加而增加

索引欄位過多,資料量巨大時,索引佔據空間可能比表更大。

當對錶的資料進行更新操作時,索引也要動態的維護,這樣就會降低資料的維護速度。

使用注意:

表資料較小時不建議使用,此時全表掃描可能效率更好。

在經常需要where、排序、分組、取區間的列上建議使用。

列不能作為表示式的一部分,或者用作函式引數,否則失效。

當表更新操作遠大於select操作時,不建議新增索引。

索引底層資料結構瞭解

B樹

平衡多路查詢樹,一棵m階的B樹。

特性:

樹中每個結點最多含有m個孩子( m >= 2 );

除根結點和葉子結點外,其他每個結點至少 m/2 個孩子。

若根結點不是葉子,至少2個孩子。

有 j 個孩子的非葉節點恰好有 j-1 個關鍵碼,關鍵碼按遞增次序排序。

B樹存在磁碟中,我們想要查詢29,查詢過程:

1. 根據根結點找到檔案目錄的根磁碟塊1,將其中資訊匯入記憶體。 【磁碟IO操作一次】

2. 此時記憶體中有兩個檔案17,35和三個儲存其他磁碟頁面地址的資料。 比較:17<29<35,因此我們訪問指標P2

3. 根據P2指標,我們定位到磁碟3,並將其資訊匯入記憶體。【磁碟IO操作2次】

4. 此時記憶體中有兩個檔案26,30和三個儲存其他磁碟頁面地址資訊的指標,26<29<30,因此我們找到P2指標。

5. 根據P2指標,定位到磁碟8,將其中資訊匯入記憶體。【磁碟IO操作3次】

B+

相對B樹的不同特性:

非葉子節點的值會以最大或最小值出現在其子節點中,即葉子節點包含所有元素。

非葉子節點帶有索引資料和指向葉子節點的指標,不包含指向實際元素資料的地址資訊。僅葉子節點有所有元素資訊。

每個元素不儲存資料,只儲存索引值即主鍵。

所有葉子節點形成一個有序連結串列。

單行查詢時與B樹相同

範圍查詢時,比如查詢大於3小於8的資料,根據單行查詢方式查詢到3之後,通過連結串列直接遍歷後面的元素。

B+樹優勢:

B+樹的磁碟讀寫代價更低。同樣的一塊磁碟大小,B樹需要儲存表元素資料,B+只需要儲存索引,可以儲存更多節點。同等元素資料量下,B+樹層數更少。

B+樹的查詢效率穩定。因為非終結點只是關鍵字的索引,所以任何關鍵字的查詢必須走一條根到葉子的路。

B+樹中葉子結點也成一個連結串列,所以B+樹在面對範圍查詢時比B樹更加高效。

InnoDB索引使用

索引分主索引和輔助索引

主索引在表建立後即存在。以主鍵為索引,葉子節點儲存元素資料。

為主鍵外的欄位新增的索引為輔助索引。以欄位內容為索引,葉子節點儲存元素對應主鍵。

MyISAM不同點在於葉子儲存的不是元素資料,而是元素資料地址。實現索引與實際資料分離。

如何高效率使用索引

獨立列查詢

SQL語句使用不當時,將無法使用現存索引而去全表掃描。所以需要注意:索引列不能是表示式的一部分,也不能是函式的引數。

通過在查詢SQL前加explain,檢視是否有使用索引。

上圖中,為timestamp欄位添加了索引。 明顯使用DATE()函式後,timestamp不使用索引,rows行數為總資料行數。

字首索引查詢(注意選擇性把握)

選擇性指不重複的索引值和資料表的記錄總數的比值。選擇性最高時,即所有鍵不重複時選擇性為1。

由上面對索引內部實現的描述我們得知,我們索引的欄位越長時,所佔記憶體也就越大。字首索引意在保持較高選擇性的情況下,取欄位的字首部分用於索引,降低記憶體使用率。

我對測試表中pdl欄位及字首部分的選擇性進行觀測如下:

如圖,字首為9時選擇性已經較高,再增加時,沒有明顯提升。這時,如果pdl欄位很長,就可以考慮使用pdl的字首9個字元作為字首索引。

alter table com_pdl_stat add key left_pdl(pdl(9));

1

注意:無法使用字首索引做ORDER BY 和 GROUP BY,考慮業務場景做取捨。

多列索引合併

很多時候我們為了查詢方便,為很多列單獨建立索引。但我們在使用where篩選時,卻多使用AND,OR等條件。

當我為表的pdl,timestamp欄位單獨設定索引時,and查詢為:

通過key標誌知道此時僅使用了pdl欄位的索引。filtered僅17.92.

這裡的僅使用了pdl欄位索引。(高效能提到5.0之後的版本會各自使用pdl和timestamp欄位,然後SQL伺服器對多個索引結果做相交(AND)或聯合操作(OR)操作,通過extra可查詢,但是我的5.7沒有這種優化,不知道為什麼~~)

如上,僅使用where條件的第一個欄位索引 或者 伺服器消耗CPU,記憶體等資源去做合併工作,都會影響查詢效能。

這是有必要合併索引,建立pdl_time(pdl, timestamp)索引後同樣的查詢結果如下:

pdl_time索引被使用,filtered達到100%。

在建立多列索引時注意:

- 通常將選擇性高的欄位放在前面

- 多列欄位的字首也可以作為索引(例如(a,b)索引時,可以單獨使用a索引,但不能單獨使用b索引)

聚簇索引

聚簇索引指的是一種資料組織結構。判斷標準為:索引的葉子節點中,儲存的是資料還是隻想資料塊的指標。如果是指向資料塊指標,則為非聚簇索引。

索引型別依賴儲存引擎,Innodb使用的是聚簇索引,MyISAM使用非聚簇索引

Innodb主鍵索引圖:

如圖為Innodb儲存引擎生成的主鍵索引結構。非葉子節點儲存主鍵,葉子節點儲存主鍵和行資料(還有事務ID和回滾指標)。

Innodb輔助索引圖:

如圖為Innodb儲存引擎生成的輔助索引結構。葉子節點儲存索引欄位和對應的主鍵值,索引到主鍵值後,根據主鍵值再去主鍵索引中查詢對應的資料。

優點在於:

減少磁碟IO次數。使用索引查詢資料時,索引節點和資料被一起載入記憶體,不需要根據指標再進行一次IO讀取。

無需維護輔助索引。當出現數據頁分裂時,無需更新索引中的資料塊指標。

非聚簇索引圖:

非聚簇索引主鍵索引和輔助索引結構一致。

瀋陽性病醫院哪家好:http://yyk.39.net/sy/zhuanke/fc844.html

瀋陽治療溼疣正規醫院:http://yyk.familydoctor.com.cn/20631/