數據庫索引的簡單介紹及優化

一、索引類型

  • 主鍵索引

一種特殊的唯一索引,不允許有空值,一般是在建表的時候同時創建索引。注意:一個表只能有一個主鍵

  • 唯一索引

唯一索引的值必須唯一,但允許有空值。如果是組合索引,則列值得組合必須唯一。

-- 創建唯一索引
ALTER TABLE table_name ADD UNIQUE(column)

  • 普通索引

最基本的索引,沒有任何限制

-- 創建普通索引
ALTER TABLE table_name ADD INDEX index_name(column)

  • 組合索引

一個索引包含多個列,多用於避免回表查詢

--創建組合索引
ALTER TABLE table_name ADD INDEX index(column1,column2,column3)

  • 全文索引

也稱全文檢索,是目前搜索引擎使用的關鍵技術

-- 創建全文索引
ALTER TABLE table_name ADD FULLTEXT(column)

索引創建後不能更改,如果要修改索引,只能刪除重建

刪除索引


DROP INDEX index_name ON table_name

查詢索引詳情


show index from table_name;

二、索引優化

  1. 前導模糊查詢不能命中索引
EXPLAIN SELECT * from test_user where name like '%王%'

在這裏插入圖片描述
非前導模糊查詢可以使用索引,可優化爲使用後置模糊查詢

EXPLAIN SELECT * from test_user where name like '王%'

在這裏插入圖片描述

  1. 數據類型出現隱式轉換的時候不會命中索引,特別是當列類型是字符串,一定要將字符常量值用引號引起來。
EXPLAIN SELECT * from test_user where name = 3;

在這裏插入圖片描述

EXPLAIN SELECT * from test_user where name = '3';

在這裏插入圖片描述

  1. 組合索引(最左原則),查詢條件是否包含最左側字段
alter table test_user add index index_zuhe(name,age,gender)

表中索引情況
在這裏插入圖片描述
根據最左原則,可以命中組合索引index_zuhe

EXPLAIN SELECT * from test_user where name = '王天' and age = 18;

在這裏插入圖片描述
注意,最左原則並不是說是查詢條件的順序:這樣也可命中

EXPLAIN SELECT * from test_user where age = 18 and name = '王天' and  gender = '男';

在這裏插入圖片描述
而是查詢條件中是否包含索引最左列字段:

EXPLAIN SELECT * from test_user where age = 18  and  gender = '男';

在這裏插入圖片描述

  1. union、in、or都能夠命中索引
EXPLAIN SELECT * from test_user where age = 18 
union all 
SELECT * from test_user where age = 19

在這裏插入圖片描述

EXPLAIN SELECT * from test_user where age in (11,12);

在這裏插入圖片描述

EXPLAIN SELECT * from test_user where age =11 or age = 12;

在這裏插入圖片描述

  1. 用or分割開的條件,如果or前的條件中列有索引,而後面的列中沒有索引,那麼涉及到的索引都不會被用到。
EXPLAIN SELECT * from test_user where age=18 or gender='男'

在這裏插入圖片描述
因爲or後面的條件列中沒有索引,那麼後面的查詢肯定要走全表掃描,在存在全表掃描的情況下,就沒有必要多一次索引掃描增加IO訪問。

  1. 負向條件查詢不能使用索引,可以優化爲in查詢。

負向條件有:!=、<>、not in、not exists、not like等。

!= 不能命中索引

EXPLAIN SELECT * from test_user where age !=18

在這裏插入圖片描述
is not null 不能命中索引

EXPLAIN SELECT * from test_user where age is not null;

在這裏插入圖片描述
is null 可以命中索引

EXPLAIN SELECT * from test_user where age is null;

在這裏插入圖片描述

  1. 數據庫執行計算不會命中索引。
EXPLAIN SELECT * from test_user where age >=27;

在這裏插入圖片描述

EXPLAIN SELECT * from test_user where age +1>=27;

在這裏插入圖片描述

  1. 建立索引的列,不允許爲null。

單列索引不存null值,複合索引不存全爲null的值,如果列允許爲null,可能會得到“不符合預期”的結果集,所以,請使用not null約束以及默認值。

三、索引設計的原則

  1. 適合索引的列是出現在where子句中的列,或者連接子句中指定的列;
  2. 基數較小的類,索引效果較差,沒有必要在此列建立索引;
  3. 使用短索引,如果對長字符串列進行索引,應該指定一個前綴長度,這樣能夠節省大量索引空間;
  4. 不要過度索引。索引需要額外的磁盤空間,並降低寫操作的性能。在修改表內容的時候,索引會進行更新甚至重構,索引列越多,這個時間就會越長。所以只保持需要的索引有利於查詢即可。

另外返回數據的比例在30%以外的情況下,優化器不會選擇使用索引。

例1:test_user表一共有17條數據,age>16 的共查詢到7條數據,那麼這個查詢是否可以命中呢?

EXPLAIN SELECT * from test_user where age > 16

例2:如果我把條件改了 ,改成age>19共查詢到4條數據,那麼是否可以命中呢?

EXPLAIN SELECT * from test_user where age > 19;

答案是例1不能命中索引,例2可以命中索引。

例1執行結果
在這裏插入圖片描述

例2執行結果
在這裏插入圖片描述
注意filtered的值就是上面我們計算的返回記錄的比例數;
因此,返回表中30%內的數據會走索引,返回超過30%數據就使用全表掃描。當然這個結論太絕對了,也並不是絕對的30%,只是一個大概的範圍。

總結

平時的開發中經常用到sql,也會對sql進行優化,對於拿捏不準的,多使用EXPLAIN命令分析一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章