索引失效 子查詢 慢查詢的起因

2021-10-06 07:50:21 字數 2246 閱讀 9550

目前,mysql作為常用的資料庫,在各類業務中被廣泛運用。但是其設計並非是十全十美,一些我們認為「高效「的語句,在執行時會花費大量的時間,導致頁面出現超時錯誤。

子查詢是乙個坑

業務中,我們定義了兩張表:使用者參加專案表(user_project)和使用者公會情況表(union_user)。user_project表中有user_id和project_id欄位來標記使用者參與專案的對應關係,同時這兩個欄位都為索引。而union_user表中有user_id和union_id欄位來標記使用者屬於哪個公會,這兩字段也全為索引。

那麼假設我們需要查詢乙個「某公會的使用者參與了哪一些專案「時,自然而然會想到用這樣的語句進行查詢:

select * from user_project 

where user_id in 

(select user_id from union_user where union_id=1)

在我們的想象中,查詢應該是這樣的:

同時,查詢中用到的鍵都建立了索引,所以應該相當快吧!?

但是事實上,這條語句執行的效率相當之差,執行一次花費的時間在10s以上。那麼問題出在**呢?

我們使用測試庫來分析一下這條語句:

可以發現user_project沒有使用user_id這個鍵進行查詢,遍歷了表中所有的4條記錄。

索引為啥沒有起效呢?這裡就要介紹兩個知識點了:

第乙個為mysql在處理所有的查詢的時候都強行轉換為聯接來執行,將每個查詢包括多表中關聯匹配,關聯子查詢,union,甚至單錶的的查詢都處理為聯接,接著mysql執行聯接,把每個聯接在處理為乙個巢狀迴圈;

第二個知識點:在mysql在處理子查詢的時候,會將子查詢改寫,mysql將會掃瞄外查詢中的所有資料,每條資料都將會傳到子查詢中進行關聯,子查詢不能首先被執行,如果外表很大的話,那麼效能上將會出現問題。

事實上,我們的查詢語句被mysql轉化成如下格式進行執行:

select * from `user_project` 

where exists 

(select * from union_user 

where union_id=1 

and union_user.user_id=user_project.user_id) 

分析其執行過程,可以發現是不會經過user_id索引的:

如何避免子查詢的這一問題呢?直接使用聯表查詢即可:

select * from `user_project`

inner join union_user using (user_id)

where union_id=1

分析該語句,發現有效使用了user_id的索引,查詢遍歷的行數大大降低。

索引失效的一些case

1.           使用or

sql如下:

select * from `user_project` where id=1 or user_id=1

雖然查詢所用的字段都是索引,但是最終mysql並沒有使用其中任何乙個。

2.           like查詢是以%開頭

sql如下:

select * from `user` where `user_name` like 'abc%'

能夠正確使用索引:

sql修改為:

select * from `user` where `user_name` like '%abc'

查詢時就會不使用索引

3.           查詢字元型不用引號

如果**使用拼串去寫語句,同時根據資料的型別決定是否加上引號,那麼會構造出這樣的語句:

select* from `user` where user_name=123

而這樣的語句實際上是不走索引的:

所以建議還是使用bind來進行引數傳遞,預防注入的同時,避免這種坑爹問題。

4.           多列索引不查詢前一部分

表中的有乙個多列索引status,用到了status和score兩個字段:

如果只查詢status,那麼索引是有效的

但是只查詢score這一字段,不去查status,那麼這個多列索引並不會起效:

總結總結一下以上的坑:

盡量使用聯表查詢來替代子查詢,因為使用子查詢會使索引失效;

查詢條件中謹慎使用or;

多列索引設定時請考慮好使用場景,如果有只查其中部分欄位的情況,該索引可能不會生效;

查詢字元型時**上引號,確保使用索引;

以%開頭的like查詢不會走索引。

————————————————

索引失效 子查詢 慢查詢的起因

目前,mysql作為常用的資料庫,在各類業務中被廣泛運用。但是其設計並非是十全十美,一些我們認為 高效 的語句,在執行時會花費大量的時間,導致頁面出現超時錯誤。業務中,我們定義了兩張表 使用者參加專案表 user project 和使用者公會情況表 union user user project表中...

MYSLQ索引 慢查詢

日誌用於記錄資料庫的運 況,以及使用者對資料庫執行的各類操作。當資料庫發生故障時,可以 根據日誌分析和解決問題,從而對資料庫進行恢復。slow query log on 開啟慢查詢日誌否則不開啟 log launch time 如果建立執行緒需要比slow launch time更多的時間,伺服器會...

sql優化哪些情況造成索引失效或查詢慢

1.sql執行順序為從右往左,where後有多個條件時,過濾資料多的條件放最右邊。2.以下情況會造成索引失效,應盡量避免。1 使用like進行模糊查詢,應為 值 不使用雙百分號,即 值 2 索引字段避免出現計算,函式,資料轉換,不使用not is null is not null等。3.避免sql過...