1、EXPLAN
善用EXPLAN來查看MYSQL的執行計劃。
以下這幾列是我們要重點關注的列:
- type列:連接類型。一條好的SQL語句至少要達到range級別。杜絕出現all級別,type的級別有all、index、range、ref、eq_ref、const。從左到右,它們的效率依次是增強的,詳情可以到[EXPLAN中type總結]瞭解。(https://blog.csdn.net/dennis211/article/details/78170079)
- key列:使用到的索引名,如果沒有使用到索引,值是NULL。(一些情況可以強制使用索引)
- key_len列:使用到的索引的長度。
- rows列:掃描的行數,該值是預估值。
- Extra列:詳細說明。常見的不太友好的值有:Using filesort,Using temporary。
2、SQL語句中IN包含的值不應該過多
MYSQL對於IN做了相應的優化,即將IN中的常亮全部存儲在一個數組裏面,而且這個數組是排好序的。但是如果數值較多,產生的性能損耗也是較大的。對於連續的數值:例如 select id from table_name where num in (1,2,3),能用BETWEEN的時候就不用IN了;也可以使用連接來代替。
3、SELECT語句必須指明字段名稱
SELECT * 增加了很多不必要的消耗(cpu,io,內存,網絡帶寬等);增加了使用覆蓋索引的可能性;而且在代碼的維護上,在增加字段之後,Mybaties可能會發生錯誤。所以要求直接在SELECT後加字段名。
4、當只需要查詢一條數據的時候,使用limit1
首下這樣可以使EXPLAN中的type列達到const類型,其次在出現一些特殊情況,查詢的數據多於一條的時候,防止Mybaties發生
executor.ExecutorException: Statement returned more than one row, where no more than one was expected.
異常。(預計的結果爲對象,結果查詢到一個集合)
5、如果排序的字段沒有用到索引,儘量別用它進行排序。
6、如果限制條件中有字段沒有索引,儘量少用OR。
OR兩邊的字段中,如果一個不是索引字段,會導致該查詢不走索引的情況,很多時候用 union all或者是union來代替OR。
7、儘量用union all 代替 union
union 和 union all 的差異主要是前者需要將結果集合並後再進行唯一性過濾操作,這樣會涉及到排序,增加大量的CPU運算,加大資源消耗及延遲。當然,union all的前提條件是兩個結果集沒有重複數據。
8、不適用ORDER BY RAND()
這種類似的操作可以在代碼中進行。
9、區分IN和EXISTS,NOT IN和NOT EXISTS
SELECT * FROM 表A WHERE id IN (SELECT id FROM 表B)
已上語句相當於
SELECT * FROM 表A WHERE EXISTS (SELECT * FROM 表B WHERE B.id = A.id)
區分IN和EXISTS主要造成的是驅動順序的改變(這是性能變化的關鍵),如果使用EXISTS,那麼是將外層表作爲驅動表,先被訪問,如果是IN,那麼會先執行子查詢。所以In合適與外表大於內表的情況。EXISTS適合於外表大於內表的情況。
關於NOT IN 和 NOT EXISTS 推薦使用NOT EXISTS。