重溫索引優化

2021-10-05 08:40:33 字數 4007 閱讀 8793

場景一:select * from user_info where id + 1 = 2;

索引的列如果是表示式的一部分或者是函式的引數,則失效。

場景二:select * from user_info where name like '%ook';

like查詢前面部分未輸入,以%開頭無法命中索引。

可以使用覆蓋索引(type=index)。

場景三:select * from user_info where id <> 1;

查詢條件使用不等式(<>或者!=)。

場景四:select * from user_info where name = 1;

查詢條件型別不一致。

字串跟數字的比較,它們型別不匹配,mysql會做隱式的型別轉換,把它們轉換為浮點數再做比較。

場景五:

mysql查詢單錶時,查詢得到的結果集佔資料總量很大比例30%,mysql會認為全表掃瞄會優於索引,則不走索引。

不要給』性別』等增加索引。如果某個資料列裡包含了均是"0/1"或「y/n」等值,即包含著許多重複的值,就算為它建立了索引,索引效果不會太好,還可能導致全表掃瞄。

場景六:

使用or連線的兩個字段,如果兩個欄位都是索引字段索引才會生效(index_merge),否則索引無效。

場景七:

使用not in的時候索引可能會失效,進而使用全表查詢。

場景一:

不使用索引首列當查詢條件(最左字首)。

create

table

`user_info`

(`id`

bigint(20

)not

null

auto_increment

,`name`

varchar(50

)not

null

default'',

`age`

int(11)

default

null

,primary

key(

`id`),

key`name_index`

(`name`))

engine

=innodb

default

charset

= utf8mb4;

create

table

`order_info`

(`id`

bigint(20

)not

null

auto_increment

,`user_id`

bigint(20

)default

null

,`product_name`

varchar(50

)not

null

default'',

`productor`

varchar(30

)default

null

,primary

key(

`id`),

key`user_product_detail_index`

(`user_id`

,`product_name`

,`productor`))

engine

=innodb

default

charset

= utf8mb4;

select_type表示了查詢的型別, 它的常用取值有:

type字段比較重要, 它提供了判斷查詢是否高效的重要依據依據. 通過 type 字段, 我們判斷此次查詢是 全表掃瞄 還是 索引掃瞄 等。

小表全表掃瞄,大表使用索引(可以是非唯一索引)。

all

<

index

< range ~ index_merge < ref < eq_ref < const < system

all 型別因為是全表掃瞄, 因此在相同的查詢條件下, 它是速度最慢的.

而 index 型別的查詢雖然不是全表掃瞄, 但是它掃瞄了所有的索引, 因此比 all 型別的稍快.

後面的幾種型別都是利用了索引來查詢資料, 因此可以過濾部分或大部分資料, 因此查詢效率就比較高了.

此字段是 mysql 在當前查詢時所真正使用到的索引.

表示查詢優化器使用了索引的位元組數. 這個字段可以評估組合索引是否完全被使用, 或只有最左部分欄位被使用到.

索引中查詢值用到的列/常量(const)

rows 也是乙個重要的字段. mysql 查詢優化器根據統計資訊, 估算 sql 要查詢到結果集需要掃瞄讀取的資料行數.

這個值非常直觀顯示 sql 的效率好壞, 原則上 rows 越少越好.

使explain中type列達到const型別。

很多時候使用 union all 或者是union(必要的時候)的方式來代替「or」會得到更好的效果。

union和union all的差異主要是前者需要將結果集合並後再進行唯一性過濾操作,這就會涉及到排序,增加大量的cpu運算,加大資源消耗及延遲。當然,union all的前提條件是兩個結果集沒有重複資料。

select

*from 表a where id in

(select id from 表b)

上面sql語句相當於

select

*from 表a where

exists

(select

*from 表b where 表b.id=表a.id)

區分in和exists主要是造成了驅動順序的改變(這是效能變化的關鍵),如果是exists,那麼以外層表為驅動表,先被訪問,如果是in,那麼先執行子查詢。所以in適合於外表大而內錶小的情況;exists適合於外表小而內錶大的情況。

select id,name from product limit

866613,20

使用上述sql語句做分頁的時候,可能有人會發現,隨著表資料量的增加,直接使用limit分頁查詢會越來越慢。

select id,name from product where id>

866612

limit

20或者 使用between語句

對於null的判斷會導致引擎放棄使用索引而進行全表掃瞄,在where子句中使用 is null 或 is not null 判斷,索引將被放棄使用,會進行全表查詢。

設定預設值

left join a表為驅動表

inner join mysql會自動找出那個資料少的表作用驅動表

right join b表為驅動表

盡量使用inner join,避免left join

利用小表去驅動大表

理解索引 索引優化

最近有個需求,要修改現有儲存結構,涉及查詢條件和查詢效率的考量,看了幾篇索引和hbase相關的文章,回憶了相關知識,結合專案需求,說說自己的理解和總結。索引結構和資料定位過程 查詢過程和高階查詢 執行計畫詳細介紹 常見優化方法 聯合索引最左字首原則 復合索引遵守 最左字首 原則,查詢條件中,使用了復...

理解索引 索引優化

最近有個需求,要修改現有儲存結構,涉及查詢條件和查詢效率的考量,看了幾篇索引和hbase相關的文章,回憶了相關知識,結合專案需求,說說自己的理解和總結。索引結構和資料定位過程 查詢過程和高階查詢 執行計畫詳細介紹 常見優化方法 聯合索引最左字首原則 復合索引遵守 最左字首 原則,查詢條件中,使用了復...

SQL優化 索引優化

一 發現哪些sql語句有效能問題 開啟mysql慢查詢日誌對sql語句進行監控 show variables like slow query log 檢視是否開啟慢查詢日誌 set global slow query log on 開啟慢查詢日誌 set global log queries not...