1. 關聯查詢優化
1.1 left join
結論:
①在優化關聯查詢時,只有在被驅動表上建立索引才有效!
②left join 時,左側的為驅動表,右側為被驅動表!
1.2 inner join
結論:inner join 時,mysql 會自己幫你把小結果集的表選為驅動表。
2. 子查詢優化
結論: 在范圍判斷時,盡量不要使用not in 和not exists,使用left join on xxx is null 代替。
3. 排序分組優化
where 條件和on 的判斷這些過濾條件,作為優先優化的部門,是要被先考慮的!其次,如果有分組和排序,那么
也要考慮grouo by 和order by。
3.1 無過濾,不索引
using filesort 說明進行了手工排序!原因在於沒有where 作為過濾條件!
結論: 無過濾,不索引。where,limt 都相當於一種過濾條件,所以才能使用上索引!
3.2 順序錯,必排序
3.3 方向反,必排序
3.4 過濾和排序使用索引的選擇
原因:所有的排序都是在條件過濾之后才執行的,所以如果條件過濾了大部分數據的話,幾百幾千條數據進行排序
其實並不是很消耗性能,即使索引優化了排序但實際提升性能很有限。相對的empno<101000 這個條件如果沒
有用到索引的話,要對幾萬條的數據進行掃描,這是非常消耗性能的,使用empno 字段的范圍查詢,過濾性更好
(empno 從100000 開始)!
結論: 當范圍條件和group by 或者order by 的字段出現二選一時,優先觀察條件字段的過濾數量,如果過濾的
數據足夠多,而需要排序的數據並不多時,優先把索引放在范圍字段上。反之,亦然。
3.5 using filesort
mysql 的排序算法:
①雙路排序
MySQL 4.1 之前是使用雙路排序,字面意思就是兩次掃描磁盤,最終得到數據,讀取行指針和orderby 列,對他
們進行排序,然后掃描已經排序好的列表,按照列表中的值重新從列表中讀取對應的數據輸出。
從磁盤取排序字段,在buffer 進行排序,再從磁盤取其他字段。
簡單來說,取一批數據,要對磁盤進行了兩次掃描,眾所周知,I\O 是很耗時的,所以在mysql4.1 之后,出現
了第二種改進的算法,就是單路排序。
②單路排序
從磁盤讀取查詢需要的所有列,按照order by 列在buffer 對它們進行排序,然后掃描排序后的列表進行輸出,
它的效率更快一些,避免了第二次讀取數據。並且把隨機IO 變成了順序IO,但是它會使用更多的空間,
因為它把每一行都保存在內存中了。
③單路排序的問題
由於單路是后出的,總體而言好過雙路。但是存在以下問題:
在sort_buffer 中,方法B 比方法A 要多占用很多空間,因為方法B 是把所有字段都取出, 所以有可能取出的數
據的總大小超出了sort_buffer 的容量,導致每次只能取sort_buffer 容量大小的數據,進行排序(創建tmp 文件,多
路合並),排完再取取sort_buffer 容量大小,再排……從而多次I/O。
結論:本來想省一次I/O 操作,反而導致了大量的I/O 操作,反而得不償失。
如何優化:
①增大sort_butter_size 參數的設置
不管用哪種算法,提高這個參數都會提高效率,當然,要根據系統的能力去提高,因為這個參數是針對每個進
程的1M-8M 之間調整。
②增大max_length_for_sort_data 參數的設置
mysql 使用單路排序的前提是排序的字段大小要小於max_length_for_sort_data。
提高這個參數,會增加用改進算法的概率。但是如果設的太高,數據總容量超出sort_buffer_size 的概率就增大,
明顯症狀是高的磁盤I/O 活動和低的處理器使用率。(1024-8192 之間調整)。
③減少select 后面的查詢的字段。
當Query 的字段大小總和小於max_length_for_sort_data 而且排序字段不是TEXT|BLOB 類型時,會用改進后的
算法——單路排序, 否則用老算法——多路排序。
兩種算法的數據都有可能超出sort_buffer 的容量,超出之后,會創建tmp 文件進行合並排序,導致多次I/O,
但是用單路排序算法的風險會更大一些,所以要提高sort_buffer_size。
3.6 使用覆蓋索引
覆蓋索引:SQL 只需要通過索引就可以返回查詢所需要的數據,而不必通過二級索引查到主鍵之后再去查詢數據。
3.7 group by
group by 使用索引的原則幾乎跟order by 一致,唯一區別是groupby 即使沒有過濾條件用到索引,也可以直
接使用索引。
----尚硅谷_mysql_高級學習筆記