在項目開發中SQL是必不可少的,表索也同樣.這些SQL的運行性能不知道嗎?有多少是命中了索引的?命中哪一個索引?索引中有哪一個是無效索引?這些無效索引是否會影響系統的性能?帶着這些問題咱們一塊兒來學習一下.
MySql中是經過 Explain 命令來分析低效SQL的執行計劃。命令的使用很簡單.
示例 explain select * from adminlog
執行結果:
id |
select_type |
table |
partitjons |
type |
possible_keys |
key |
key_len |
ref |
row |
filtered |
Extra |
1 |
SIMPLE |
adminlog |
|
ALL |
|
|
|
|
2 |
100 |
|
執行結果每一列的說明:
一、 select_type : 查詢類型,常見的值[SIMPLE:簡單表,不使用錶鏈接或子查詢。PRIMARY : 主查詢,外層的查詢。UNION 第二個或者後面的查詢語句。SUBQUERY : 子查詢中的第一個select]
二、table :輸出結果的表
三、type : 表示MySql在表中找到所需行的方式,或者叫訪問類型。常見的類型:
ALL |
index |
range |
ref |
eq_ref |
const,system |
NULL |
從左到右,性能由最差到最好。
3.1 type=ALL 全表掃描,
3.2 type=index 索引全掃描,遍歷整個索引來查詢匹配的行
3.3 type=range 索引範圍掃描,常見於 <,<=,>,>=,between,in等操做符。
例
explain select * from adminlog where id>0 ,
explain select * from adminlog where id>0 and id<=100
explain select * from adminlog where id in (1,2)
3.4 type=ref 使用非惟一索引或惟一索引的前綴掃描,返回匹配某個單獨值的記錄行。ref還常常出如今JOIN操做中
3.5 type=eq_ref 相似於ref,區別就在使用的索引是惟一索引,對於每一個索引鍵值,表中有一條記錄匹配;簡單來講,說是多表鏈接中使用 主建或惟一健做爲關聯條件
3.6 type=const/system 單表中最多有一個匹配行。主要用於比較primary key [主鍵索引]或者unique[惟一]索引,由於數據都是惟一的,因此性能最優。條件使用=。
3.7 type=NULL 不用訪問表或者索引,直接就可以獲得結果
例 explain select 1 from dual,類型type 還有其餘值 如ref_or_null : 與ref 相似,區別在於條件中包含對NULL的查詢. index_merge : 索引合併優化, unique_subquery : in的後面是一個主鍵字段的子查詢。index_subquery : 與 unique_subquery 相似,區別在於in的後面是查詢非惟一索引字段的子查詢
四、possible_keys : 可能使用的索引列表.
五、key : 實現執行使用索引列表
六、key_len : 索引的長度
七、ref : 顯示使用哪一個列或常數與key一塊兒從表中選擇行。
八、row : 執行查詢的行數,簡單且重要,數值越大越很差,說明沒有用好索引
九、filtered:
十、Extra: 該列包含MySQL解決查詢的詳細信息。
10.1 Not exists
10.2 range checked for each record
沒有找到合適的索引
10.5 using index 只使用索引樹中的信息而不須要進一步搜索讀取實際的行來檢索表中的信息。就是建議取索引列。這樣就能夠不要經過索引去實際表中找數據了。直接返回索引列的數據。一次查詢。不然就是索引表查一次,實際表中查一次。
10.6 using temporary
爲了解決查詢,MySQL須要建立一個臨時表來容納結果。典型狀況如查詢包含能夠按不一樣狀況列出列的GROUP BY和ORDER BY子句時。
無效索引: 數據變化不大的列。如XX類型,是否有效,項目ID等列的索引都是無效的。這些無效索引仍是影響Insert 、Update、Delete 語句的性能。由於這些語包的執行都要對索引表進行更新。又由於這些表的值變化不大,數據庫很難爲他們合理分配索引。因此影響語句的性能。
IN,OR 是否會走索引:
一條SQL會不會走索引一個看條件使用的運算符,另外一個看有沒有索引。因此SQL會不會走索引和IN.OR,group by 沒有關係。
什麼運算符不走索引,<>,!=
OR 有個點要注意一下:就OR先後兩個條件都要有索引整個SQL纔會使用索引。只要有一個條件沒索引那麼整個SQL都不使用索引。
若是出現OR的一個條件沒有索引時,建議使用
union
例:
explain SELECT * FROM cbdfinance.adminlog where id = 1
union SELECT * FROM cbdfinance.adminlog where OriginalData='UpdateModelErrorMsg';數據庫
結果:性能
1 |
PRIMARY |
adminlog |
|
const |
PRIMARY |
PRIMARY |
4 |
const |
1 |
100.00 |
|
2 |
UNION |
adminlog |
|
ALL |
|
|
|
|
11 |
10.00 |
Using where |
|
UNION RESULT |
<union1,2> |
|
ALL |
|
|
|
|
|
|
Using temporary |
使用OR第二個條件沒有索引:
explain SELECT * FROM cbdfinance.adminlog where id = 1 or OriginalData='UpdateModelErrorMsg';
結果:
1 |
SIMPLE |
adminlog |
|
ALL |
PRIMARY |
|
|
|
11 |
18.18 |
Using where |
explain SELECT * FROM cbdfinance.adminlog where id = 1 or id=2;
explain SELECT * FROM cbdfinance.adminlog where id = 1 or SearchText1='UpdateModelErrorMsg';
explain SELECT * FROM cbdfinance.adminlog where id in (1,2)
explain SELECT * FROM cbdfinance.adminlog group by SearchText1