場景一: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...