1. 程式人生 > 實用技巧 >MYSQL 索引(一)--- 簡介

MYSQL 索引(一)--- 簡介

簡介

Mysql 官方定義 : 索引(Index) 是幫助 Mysql 高效獲取資料的資料結構。

索引的目的在於提交查詢效率,可以類比字典。簡單理解為 “排好序的快讀查詢資料結構”。

資料本身之外,資料庫還維護著一個滿足特定查詢演算法的資料結構哦,這些資料結構以某種方式指向資料,這樣就可以在這些資料結構的基礎上實現高階查詢演算法。這種資料結構就是索引。

一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存在在盤上。

優劣

優勢:

  1. 提高了資料檢索效率,降低資料庫的 IO 成本
  2. 通過索引對資料進行排序,降低資料排序的成本,降低了 CPU 的消耗

劣勢:

  1. 實際上索引也是一張表,該表儲存了主鍵和索引欄位,並指向實體表的記錄,所以索引列也要佔用空間
  2. 索引大大提高了查詢速度,同時會降低更新表的速度。因為更新表時不僅要儲存資料,還要儲存索引檔案每次更新添加了索引列的欄位。

索引分類

  • 單值索引:即一個索引只包含單個列,一個表可以有多個單值索引
  • 唯一索引:索引列的值必須唯一,但允許有空值
  • 複合索引:一個索引包含單個列

基本語法

# 建立 如果是 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

索引建立情況

  1. 主鍵自動建立唯一索引
  2. 頻繁作為查詢條件的欄位應該建立索引
  3. 查詢中與其他表關聯的欄位,外來鍵關係應該建立索引
  4. 頻更新的欄位不適合做索引
  5. Where 條件中用不到的欄位不適合建立索引
  6. 單鍵/組合鍵索引的選擇問題(高併發下傾向建立組合索引)
  7. 查詢中排序的欄位,排序欄位若通過索引去訪問將大大提高排序速度
  8. 查詢中統計或者分組的欄位

不建立索引情況

  1. 表記錄太少
  2. 經常增刪改的表
  3. 資料重複且分佈平均的表字段,應該只為最經常查詢和排序的欄位建立索引

Explain

檢視執行計劃: explain + SQL

  • 表的讀取速度
  • 資料讀取操作的操作型別
  • 那些索引可以使用
  • 那些索引被實際使用
  • 表之間的引用
  • 每張表有多少行被優化器查詢

id

id : select 查詢的序列號,包含一組數字,表示查詢中執行 select 子句或操作表的順序

  1. id 相同 : 執行順序由上至下
  2. id不同 :如果是子查詢,id 的序號會遞增,id 值越大優先順序越高,越先被執行
  3. 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 操作,在中到第一匹配的元組後即停止找同樣值的動作 |

使用情況

  1. 觀察,至少跑一天,看看生產的慢 SQL 情況
  2. 開啟慢查詢日誌,設定閾值,比如超過 5 秒的就是慢 SQL,並把他們抓取出來
  3. explain + 慢 SQL 分析
  4. show profile : 查詢 SQL 在 Mysql 伺服器裡面的執行細節和生命週期情況
  5. 運維經理或DBA,進行 SQL 資料庫伺服器引數調優