mysql數據庫sql優化---索引失效問題

總覽

我上家公司作的項目也是互聯網項目,常常會遇到性能問題,在提高性能方面除了使用緩存,使用多線程,拆分服務等等 還有一個最經常使用的方法就是排除掉項目中慢sql。 慢sql對項目運行真是很是大。咱們項目就由於有慢sql阻塞了數據庫服務器,致使了後面執行的sql沒法運行,致使服務器響應超時。 一個頁面要刷20秒才能出來。 這對一個互聯網項目是沒法忍受的。下面就介紹一下常見的幾個慢sqlweb

條件字段函數操做

假設有一個交易系統,其中有一個表叫trade表包含了流水號(tradeid)、交易員id(operator)、交易時間(t_modified)等字段。sql

create table tradelog(
	id int(11) NOt NULL,
	tradeid varchar(32) default null,
	operator int(11) Default NULL,
	t_modified datetime default null,
	primary key (id),
	key tradeid (tradeid),
	key t_modified	 (t_modified)
) engine=innodb default charset=utf8mb4;

假如,表中假了2016年到2018年中的數據,如今要統計全部年份中7月份的交易記錄總數。你sql也許會是這樣的數據庫

select  count(1) from tradelog where month(t_modified)=7;

雖然t_modified字段上有索引,但這仍然是一個慢sql,由於若是字段上作了函數計算就不會使用索引了。
下面這個圖就是t_modified字段的索引示意圖, 方框上面的數字是month()函數對應的值 。方塊中的值是索引值 ,B+樹數會用全部值,構造一個樹結構,是一個二叉數,全部的值會放在最後一層。
由於對字段進行了計算,計算出來的結果,和索引的值是不一致的,而這種不一致會形成,樹關索引的有序性被破壞,由於一開始就不能走樹狀索引。 這就是爲何字段進行函數計算了就沒法使用索引的緣由了。
在這裏插入圖片描述
在這個例子中,優化器雖然放棄了樹狀索引,可是優化器可使用主鍵索引,和t_modified索引 。優化器會選擇一個小的索引,最終使用的是t_modified索引.
使用explain 對sql進行分析
在這裏插入圖片描述
key = t_modified是表明使用這個索引,rows是表明掃描了多少行。extra字段的using index表示的是使用了索引覆蓋。(沒有回表操做)這裏的rows也是Mysql優化器作出的選擇,若是行數很是短的話,優化器就不會使用索引了。 也一樣會進行全表掃描。編程

如今咱們對sql進行優化緩存

在這裏插入圖片描述
這樣就會使用樹關索引了。rows數就會大符減小。服務器

隱式類型轉換

explain  select * from tradelog where tradeid = 100;

你們能夠先看看這條sql,tradeid上面是有索引的,可是通過分析這個sql也是走的全表掃描。這是爲何呢?
由於咱們在定義字段類型的時候tradeid是varchar類型的,而他的條件是非varchar類型的,裏面包含了類型轉換,由於不能走索引。多線程

類型轉換的規則是什麼?

字符串和數字作比較的話,會將字符串轉成數字svg

爲何有數據類型轉換,就須要走全表掃描 ?

下面咱們來看sql函數

select * from  tradelog where tradeid= 110717;

對優化器來講這個語句至關於工具

select * from tradelog where CAST(tradeid As signed int )= 110717

咱們以前已經說過了,對字段進行函數操做,會改變樹狀索引的順序,優化器會放棄走樹搜索功能。

兩個表之間的編程不一致

兩個表之間的編碼不一致一樣會致使不能走樹索引。這裏就不在給予例子,這種狀況出現的機率比較少,由於咱們在建立表的時候,通常是經過工具,表的編碼都是同樣的。

總結

對索引字段作函數操做,可能會破壞索引值的有序性,所以優化器就放器走樹搜索功能。