MYSQL 索引(一)--- 簡介
簡介
Mysql 官方定義 : 索引(Index) 是幫助 Mysql 高效獲取資料的資料結構。
索引的目的在於提交查詢效率,可以類比字典。簡單理解為 “排好序的快讀查詢資料結構”。
資料本身之外,資料庫還維護著一個滿足特定查詢演算法的資料結構哦,這些資料結構以某種方式指向資料,這樣就可以在這些資料結構的基礎上實現高階查詢演算法。這種資料結構就是索引。
一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存在在盤上。
優劣
優勢:
- 提高了資料檢索效率,降低資料庫的 IO 成本
- 通過索引對資料進行排序,降低資料排序的成本,降低了 CPU 的消耗
劣勢:
- 實際上索引也是一張表,該表儲存了主鍵和索引欄位,並指向實體表的記錄,所以索引列也要佔用空間
- 索引大大提高了查詢速度,同時會降低更新表的速度。因為更新表時不僅要儲存資料,還要儲存索引檔案每次更新添加了索引列的欄位。
索引分類
- 單值索引:即一個索引只包含單個列,一個表可以有多個單值索引
- 唯一索引:索引列的值必須唯一,但允許有空值
- 複合索引:一個索引包含單個列
基本語法
# 建立 如果是 CHAR,VARCHAR 型別,length可以小於欄位實際長度,如果是 BLOB和TEXT型別,必須指定 length CREATE [UNIQUE] INDEX index_name ON table_name(columnname(length)); # 或 ALTER table_name ADD [UNIQUE] INDEX [index_name] ON (column(length)) #刪除 DROP INDEX [index_name] ON table_name #檢視 SHOW INDEX FREOM table_name\G
索引建立情況
- 主鍵自動建立唯一索引
- 頻繁作為查詢條件的欄位應該建立索引
- 查詢中與其他表關聯的欄位,外來鍵關係應該建立索引
- 頻更新的欄位不適合做索引
- Where 條件中用不到的欄位不適合建立索引
- 單鍵/組合鍵索引的選擇問題(高併發下傾向建立組合索引)
- 查詢中排序的欄位,排序欄位若通過索引去訪問將大大提高排序速度
- 查詢中統計或者分組的欄位
不建立索引情況
- 表記錄太少
- 經常增刪改的表
- 資料重複且分佈平均的表字段,應該只為最經常查詢和排序的欄位建立索引
Explain
檢視執行計劃: explain + SQL
- 表的讀取速度
- 資料讀取操作的操作型別
- 那些索引可以使用
- 那些索引被實際使用
- 表之間的引用
- 每張表有多少行被優化器查詢
id
id : select 查詢的序列號,包含一組數字,表示查詢中執行 select 子句或操作表的順序
- id 相同 : 執行順序由上至下
- id不同 :如果是子查詢,id 的序號會遞增,id 值越大優先順序越高,越先被執行
- id 有相同又有不同的 ,同時存在
select_type
查詢型別 | 含義 |
---|---|
SIMPLE | 簡單的 select 查詢,不包含子查詢或者 UNION |
PRIMARY | 查詢中包含任何複雜的子部分,最外層查詢則被標準為 PRIMARY |
SUBQUERY | 在 SELECT 或 WHERE 列表中包含了子查詢 |
DERIVED | 在 FROM 列表中包含的子查詢被標記為 DERIVED(衍生) ,MYSQL 會遞迴執行這些子查詢,把結果放在臨時表裡 |
UNION | 若第二個 SELECT 出現在 UNION 之後,則被標記為 UNION; |
若 UNION 包含在 FROM 子句的子查詢中,外層 SELECT將被標記為:DERIVED | |
UNION RESULT | 從 UNION 表獲取結果的 SELECT |
table
顯示這一行資料是關於哪張表
type
type: 顯示查詢使用了哪種查詢型別。常見查詢型別如下:
ALL | index | range | ref | eq_ref | const, system | NULL |
---|
從最好到最差依次是:
system > const > eq_ref > ref > range > index > ALL
訪問型別 | 含義 |
---|---|
system | 表只有一行記錄(等於系統表),這是 const 型別的特例,平時不會出現,可以忽略不計 |
const | 表示通過索引一次就找到了, const 用於比較 primary或者 unique索引。因為只匹配到一行資料,所以很快。如將主鍵置於 where 列表中, Mysql 就能將該查詢轉換為一個常量 |
eq_ref | 唯一性索引掃描,對於每個索引建,表中只有一行資料與之匹配。常見於主鍵或唯一性索引掃描 |
ref | 非唯一性索引掃描,返回匹配某個單獨值的所有航,本質上也是一種索引訪問,它返回所有匹配某個單獨值的行。然而,它可能會找到多個符合條件的行,所以他應該是屬於查詢和掃描的混合體 |
range | 只檢索非定範圍的行,使用一個索引來選擇行。key 列顯示使用了那個索引。 |
一般就是在你的 where 語句中出現了 between、<、>、in 等的查詢。這種範圍掃描索引掃描比全表掃描要好,因為他只需要開始於索引的某一點,而結束語另一點,不用掃描全部索引 | |
index | Full Index Scan,index 與 ALL 區別為 index 型別只遍歷索引樹。這通常比 ALL 快,因為索引檔案通常比資料檔案小。(雖然 all 和 index 都是讀全表,但 index是從索引中讀出,而 all 是從硬碟中讀的) |
all | Full Table Scan,將遍歷全表以找到匹配的行 |
possible_keys
顯示可能應用到這張表中的索引,一個或多個。查詢涉及到的欄位上若存在索引,則該索引將被列出,但不一定被查詢實際使用。
key
實際使用的索引。如果為 NULL,則沒有使用索引。
查詢中若使用了覆蓋索引,則該索引僅出現在 key 列表中。
key_len
表示索引中使用的位元組數,可通過該列計算查詢中使用的索引的長度。在不損失精確性的情況下,長度越短越好。 key_len 顯示的值為索引欄位的最大可能長度,並非實際長度,即 key_len 是根據表定義計算而得,並不是通過表內檢索出的。
ref
顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或常量被用於查詢索引列上的值
row
根據表統計資訊及索引選用情況,大致估算出找到所需記錄所需要讀取的行數
extra
不適合在其他列中顯示但十分重要的額外資訊
資訊 | 含義 |
---|---|
Using filesort | 說明 mysql 會對資料使用一個額外的索引排序,而不是按照表內的索引順序進行讀取。Mysql 中無法利用索引完成的排序操作稱為“檔案排序”。 |
Usering temporary | 使用了臨時表儲存中間結果,Mysql 在對查詢結果排序時使用臨時表,常見於排序 order by 和分組查詢 group by |
Using index | 表示相應的 select 操作中使用了覆蓋索引,避免訪問了表的資料行,效率不錯。 |
如果同時出現 using where ,表明索引被用來執行索引鍵值的查詢。 | |
如果沒有同時出現 using where,表明索引用來讀取資料而非執行查詢動作。 |
Covering Index 覆蓋索引。
理解方式一 : select 的資料列只用從索引中就能夠取得,不必讀取資料行, Mysql 可以利用索引返回 select 列表中的欄位,而不必根據索引再次讀取資料檔案,換句話說查詢列要被所建的索引覆蓋。
理解方式二 : 索引是高校找到行的一個方法,但是一般資料庫也能使用索引找到一個列的資料。因此它不必讀取整個行,畢竟索引葉子節點儲存了他們索引的資料;當能通過都區索引就可以得到想要的資料,那就不需要讀取行了。一個索引包含(或覆蓋)了滿足查詢結果的資料就叫做覆蓋索引 |
| using where | 表示使用了 where 過濾 |
| using join buffer | 使用了連線快取 |
| impossible where | where 子句的值總是 false,不能用來獲取任何元組 |
| select tables optimized away | 在沒有 group by 子句的情況下,基於索引優化 MIN/MAX 操作或者對於 MyISAM 儲存引擎優化 COUNT(*) 操作,不必等到執行階段在進行計算,查詢執行計劃生成的階段即完成優化 |
| distinct | 優化 distinct 操作,在中到第一匹配的元組後即停止找同樣值的動作 |
使用情況
- 觀察,至少跑一天,看看生產的慢 SQL 情況
- 開啟慢查詢日誌,設定閾值,比如超過 5 秒的就是慢 SQL,並把他們抓取出來
- explain + 慢 SQL 分析
- show profile : 查詢 SQL 在 Mysql 伺服器裡面的執行細節和生命週期情況
- 運維經理或DBA,進行 SQL 資料庫伺服器引數調優