MySQL调优(五):MySQL查询优化分析
查詢慢的原因
優化數據訪問
一個有趣的現象:如果可能的結果非常大的話,有可能就不用索引來排序了。
實際處理的時候,可能會有優化器對結果產生一些影響。
《高性能MySQL》中說整體數據訪問量的閾值是30%,但是實際測試中并沒有測出準確值,所以還是要根據實際案例,具體問題具體分析。
思考:下面這個limit怎么通過子查詢進行優化?
避免:
1、避免查詢不需要的記錄
我們常常會誤以為mysql會只返回需要的數據,實際上mysql卻是先返回全部結果再進行計算,在日常的開發習慣中,經常是先用select語句查詢大量的結果,然后獲取前面的N行后關閉結果集。
優化方式是在查詢后面添加limit
2、避免多表關聯時返回全部列
select * from actor inner join film_actor using(actor_id) inner join film using(film_id) where film.title='Academy Dinosaur';select actor.* from actor...;3、避免總是取出全部列
在公司的企業需求中,禁止使用select *,雖然這種方式能夠簡化開發,但是會影響查詢的性能,所以盡量不要使用
4、避免重復查詢相同的數據
如果需要不斷的重復執行相同的查詢,且每次返回完全相同的數據,因此,基于這樣的應用場景,我們可以將這部分數據緩存起來,這樣的話能夠提高查詢效率
執行過程的優化
查詢緩存(8版本取消了)
在解析一個查詢語句之前,如果查詢緩存是打開的,那么mysql會優先檢查這個查詢是否命中查詢緩存中的數據,如果查詢恰好命中了查詢緩存,那么會在返回結果之前會檢查用戶權限,如果權限沒有問題,那么mysql會跳過所有的階段,就直接從緩存中拿到結果并返回給客戶端
查詢優化處理
語法解析器和預處理
解析樹:AST Tree
mysql通過關鍵字將SQL語句進行解析,并生成一顆解析樹,mysql解析器將使用mysql語法規則驗證和解析查詢,例如驗證使用使用了錯誤的關鍵字或者順序是否正確等等,預處理器會進一步檢查解析樹是否合法,例如表名和列名是否存在,是否有歧義,還會驗證權限等等
查詢優化器
CBO:基于成本的優化
RBO:基于規則的優化
當語法樹沒有問題之后,相應的要由優化器將其轉成執行計劃,一條查詢語句可以使用非常多的執行方式,最后都可以得到對應的結果,但是不同的執行方式帶來的效率是不同的,優化器的最主要目的就是要選擇最有效的執行計劃
mysql使用的是基于成本的優化器,在優化的時候會嘗試預測一個查詢使用某種查詢計劃時候的成本,并選擇其中成本最小的一個
last_query_cost查看上一次查詢的代價
MySQL中可以通過show status like ‘last_query_cost’ 來查看查上一個查詢的代價,而且它是io_cost和cpu_cost的開銷總和,它通常也是我們評價一個查詢的執行效率的一個常用指標。
(1)它是作為比較各個查詢之間的開銷的一個依據。
(2)它只能檢測比較簡單的查詢開銷,對于包含子查詢和union的查詢是測試不出來的。
(3)當我們執行查詢的時候,MySQL會自動生成一個執行計劃,也就是query plan,而且通常有很多種不同的實現方式,它會選擇最低的那一個,而這個cost值就是開銷最低的那一個。
(4)它對于比較我們的開銷是非常有用的,特別是我們有好幾種查詢方式可選的時候。
關聯查詢
排序優化
無論如何排序都是一個成本很高的操作,所以從性能的角度出發,應該盡可能避免排序或者盡可能避免對大量數據進行排序。
推薦使用利用索引進行排序,但是當不能使用索引的時候,mysql就需要自己進行排序,如果數據量小則再內存中進行,如果數據量大就需要使用磁盤,mysql中稱之為filesort。
如果需要排序的數據量小于排序緩沖區(show variables like ‘%sort_buffer_size%’😉,mysql使用內存進行快速排序操作,如果內存不夠排序,那么mysql就會先將樹分塊,對每個獨立的塊使用快速排序進行排序,并將各個塊的排序結果存放再磁盤上,然后將各個排好序的塊進行合并,最后返回排序結果
兩次傳輸排序
第一次數據讀取是將需要排序的字段讀取出來,然后進行排序,第二次是將排好序的結果按照需要去讀取數據行。
這種方式效率比較低,原因是第二次讀取數據的時候因為已經排好序,需要去讀取所有記錄而此時更多的是隨機IO,讀取數據成本會比較高
兩次傳輸的優勢,在排序的時候存儲盡可能少的數據,讓排序緩沖區可以盡可能多的容納行數來進行排序操作
單次傳輸排序
先讀取查詢所需要的所有列,然后再根據給定列進行排序,最后直接返回排序結果,此方式只需要一次順序IO讀取所有的數據,而無須任何的隨機IO,問題在于查詢的列特別多的時候,會占用大量的存儲空間,無法存儲大量的數據
總結
以上是生活随笔為你收集整理的MySQL调优(五):MySQL查询优化分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis实战(五):Redis的持久化
- 下一篇: Redis实战(六):Redis的集群: