Mysql索引使用 索引優化(二)

2021-10-06 20:30:55 字數 3827 閱讀 8880

一、什麼情況下適合使用索引?

欄位的數值有唯一性的限制,比如使用者名稱,可以用唯一索引或者主鍵索引

頻繁作為 where 查詢條件的字段,尤其在資料表大的情況下

需要經常 group by 和 order by 的列

索引就是讓資料按照某種順序進行儲存或檢索,因此當我們使用 group by 對資料進行分組查詢,或者使用 order by 對資料進行排序的時候,就需要對分組或者排序的字段進行索引。

如果我們需要對不同字段同時進行 group by 和 order by,那麼是不是需要單獨建立不同的索引呢?

當我們對 user_id 和 comment_time 分別建立索引,執行下面的 sql 查詢:

select user_id,

count(*

)as num from product_comment group

by user_id order

by comment_time desc

limit

100

執行結果(執行時間 >100s):

實際上多個單列索引在多條件查詢時只會生效乙個索引(mysql 會選擇其中乙個限制最嚴格的作為索引),所以在多條件聯合查詢的時候最好建立聯合索引。

我們建立聯合索引 (user_id, comment_time),再來看下查詢的時間,查詢時間為 0.775s

如果我們建立聯合索引的順序為 (comment_time, user_id) 呢?執行時間為 1.990s,

這是因為在進行 select 查詢的時候,先進行 group by,再對資料進行 order by 的操作,所以按照這個聯合索引的順序效率是最高的。

update、delete 的 where 條件列,一般也需要建立索引

distinct 字段需要建立索引

做多表 join 連線操作時,建立索引需要注意以下的原則

首先,連線表的數量盡量不要超過 3 張,因為每增加一張表就相當於增加了一次巢狀的迴圈,數量級增長會非常快,嚴重影響查詢的效率。

其次,對 where 條件建立索引,因為 where 才是對資料條件的過濾。如果在資料量非常大的情況下,沒有 where 條件過濾是非常可怕的。

最後,對用於連線的字段建立索引,並且該字段在多張表中的型別必須一致。比如 user_id 在 product_comment 表和 user 表中都為 int(11) 型別,而不能乙個為 int 另乙個為 varchar 型別。

二、 什麼情況下不適合使用索引?

在資料表中的資料行數比較少的情況下,比如不到 1000 行,是不需要建立索引的

當資料重複度大,比如高於 10% 的時候,也不需要對這個字段使用索引 ,如果是性別這個字段,就不需要對它建立索引。

where 條件(包括 group by、order by)裡用不到的字段不需要建立索引,索引的價值是快速定位,如果起不到定位的字段通常是不需要建立索引的。

頻繁更新的字段不一定要建立索引。因為更新資料的時候,也需要更新索引,如果索引太多,在更新索引的時候也會造成負擔,從而影響效率。

三、什麼情況下索引失效?

如果索引進行了表示式計算,則會失效

explain

select comment_id, user_id, comment_text from product_comment

where comment_id+1=

900001

-- 解決 :重寫sql

select comment_id, user_id, comment_text from product_comment

where comment_id =

900000

如果對索引使用函式,也會造成失效

-- 對 comment_text 的前三位為 abc 的內容進行條件篩選

explain

select comment_id, user_id, comment_text from product_comment

where substring(comment_text,1,

3)='abc'

-- 解決 :重寫sql

select comment_id, user_id, comment_text from product_comment

where comment_text like

'abc%'

在 where 子句中,如果在 or 前的條件列進行了索引,而在 or 後的條件列沒有進行索引,那麼索引會失效。

-- comment_id 是主鍵,而 comment_text 沒有進行索引,因為 or 的含義就是兩個只要滿足乙個即可,

-- 因此只有乙個條件列進行了索引是沒有意義的,只要有條件列沒有進行索引,就會進行全表掃瞄

explain

select comment_id, user_id, comment_text from product_comment

where comment_id =

900001

or comment_text =

'462eed7ac6e791292a79'

-- 解決 :對comment_text 建立索引

. 當我們使用 like 進行模糊查詢的時候,後面不能是 %

explain

select comment_id, user_id, comment_text from product_comment

where comment_text like

'%abc'

索引列與 null 或者 not null 進行判斷的時候也會失效。

-- 這是因為索引並不儲存空值,所以最好在設計資料表的時候就將字段設定為 not null 約束,

-- 比如你可以將 int 型別的字段,預設值設定為 0。將字元型別的預設值設定為空字串 (』』)。

我們在使用聯合索引的時候要注意最左原則,

假設我們有 x、y、z 三個字段,建立聯合索引(x, y, z)之後,我們可以把 x、y、z 分別模擬成「百分位」、「十分位」和「個位」。

查詢「x=9 and y=8 and z=7」的過程,就是在乙個由小到大排列的數值串行中尋找「987」,可以很快找到。

查詢「y=8 and z=7」,就用不上索引了,因為可能存在 187、287、387、487………這樣就必須掃瞄所有數值。

查詢「z=7 and y=8 and x=9」的時候,如果三個字段 x、y、z 在條件查詢的時候是亂序的,但採用的是等值查詢(=)或者是 in 查詢,那麼 mysql 的優化器可以自動幫我們調整為可以使用聯合索引的形式。

當我們查詢「x=9 and y>8 and z=7」的時候,如果建立了 (x,y,z) 順序的索引,這時候 z 是用不上索引的。這是因為 mysql 在匹配聯合索引最左字首的時候,如果遇到了範圍查詢,比如()和 between 等,就會停止匹配。索引列最多作用於乙個範圍列,對於後面的 z 來說,就沒法使用到索引了。

通過這個我們也可以知道,聯合索引的最左字首匹配原則針對的是建立的聯合索引中的順序,如果建立了聯合索引(x,y,z),那麼這個索引的使用順序就很重要了。如果在條件語句中只有 y 和 z,那麼就用不上聯合索引。

此外,sql 條件語句中的字段順序並不重要,因為在邏輯查詢優化階段會自動進行查詢重寫。

最後你需要記住,如果我們遇到了範圍條件查詢,比如()(>=)和 between 等,那麼範圍列後的列就無法使用到索引了。

mysql 優化 聚集索引 mysql 索引優化

一.聚集索引 clustered index innodb預設依據主鍵列聚集,myisam不使用 特點 b樹每個葉子包含實際資料行,資料按照索引順序地儲存在物理頁上。優點 1.範圍查詢,獲取指定id的全部資料只需從磁碟讀取少量資料頁 如果不使用聚集索引,每條資料可能引起一次磁碟io。2.由於索引和資...

mysql索引優化原則 MySQL 索引優化原則

索引優化原則 1 最左字首匹配原則,聯合索引,mysql會從做向右匹配直到遇到範圍查詢 3 and d 4 如果建立 a,b,c,d 順序的索引,d是用不到索引的,如果建立 a,b,d,c 的索引則都可以用到,a,b,d的順序可以任意調整。2 和in可以亂序,比如a 1 and b 2 and c ...

mysql索引優化原則 MySQL索引優化

mysql官方對索引的定義 索引是幫助mysql高效獲取資料的資料結構。索引是在儲存引擎中實現的,所以每種儲存引擎中的索引都不一樣。如myisam和innodb儲存引擎只支援btree索引 memory和heap儲存引擎可以支援hash和btree索引。這裡僅針對常用的innodb儲存引擎所支援的b...