目前,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轉化成如下格式進行執行:
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的索引,查詢遍歷的行數大大降低。
sql如下:
select * from `user_project` where id=1 or user_id=1
雖然查詢所用的字段都是索引,但是最終mysql並沒有使用其中任何乙個。
sql如下:
select * from `user` where `user_name` like 'abc%'
能夠正確使用索引:
sql修改為:
select * from `user` where `user_name` like '%abc'
查詢時就會不使用索引
如果**使用拼串去寫語句,同時根據資料的型別決定是否加上引號,那麼會構造出這樣的語句:
select* from `user` where user_name=123
而這樣的語句實際上是不走索引的:
所以建議還是使用bind來進行引數傳遞,預防注入的同時,避免這種坑爹問題。
表中的有乙個多列索引status,用到了status和score兩個字段:
如果只查詢status,那麼索引是有效的
但是只查詢score這一字段,不去查status,那麼這個多列索引並不會起效:
總結一下以上的坑:
索引失效 子查詢 慢查詢的起因
目前,mysql作為常用的資料庫,在各類業務中被廣泛運用。但是其設計並非是十全十美,一些我們認為 高效 的語句,在執行時會花費大量的時間,導致頁面出現超時錯誤。子查詢是乙個坑 業務中,我們定義了兩張表 使用者參加專案表 user project 和使用者公會情況表 union user user p...
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過...