高效能mysql 第六章查詢效能最佳化 總結(上)查詢的執行過程

來源:互聯網
上載者:User

標籤:目的   參考   建立   成本   儲存   結合   不同的   ica   引擎   

6  查詢效能最佳化

6.1為什麼查詢會變慢

   這裡說明了的查詢執行循環,從用戶端到伺服器端,伺服器端解析,最佳化器產生執行計畫,執行(可以細分,大體過程可以通過show profile查看),從伺服器端返回用戶端結果。

   而執行部分作為最重要的一環,需要做的事情比較多,而不合適的query往往讓執行過程做了不必要的操作,或者不能使用更優秀的底層資料結構,從而用時更久。

 

6.2慢查詢基礎:最佳化資料訪問

   訪問資料量多大,超過實際所需是慢查詢的一個原因。導致這種情況的原因大致有兩個

1.應用程式向mysql服務需求的了超過需要的,或重複的資料,比如select * 。

2.mysql伺服器執行過程中訪問了超過需要的資料。

 

我們先來看第一種原因

6.2.1向資料庫請求了超過需要的資料

1.請求了超過需要的行,如沒有使用limit,請求了100行資料,但是只使用了10行。

2.使用select * 返回了不需要的列資料,尤其是多表關聯查詢是情況更突出,應該做的是只返回我們需要的列。

3.用戶端如果使用了緩衝,並且該部分緩衝被接下來的資料需求命中,那麼就沒有必要再向伺服器發送資料請求。

 

6.2.2mysql掃描了額外的紀錄

慢查詢日誌中的三個衡量查詢開銷的指標:1.回應時間,2。掃描行數,3.返回行數

1.回應時間

回應時間包括服務時間與排隊時間。

回應時間在不同的伺服器環境,應用環境下都會不同。文中提到使用‘快速上限法’(中文版譯名):通過query的執行計畫,計算需要的順序io與隨機io次數,再結合當前環境下一次io的時間。最後做一次加總可以獲得一個‘參考值‘。(可以看出來,這樣的一種方法實操性並不強,因為並不是每一個query我們都能相對準確的估算io次數,不同伺服器環境下,甚至統一伺服器的不同時間,io的效率也會不同。     不過這裡我們可以看出來,io是執行過程中相對比較耗時的一步)

 

2.掃描行數與返回行數

 掃描行數與返回行數單獨都是不能體現出任何query的效率的,只有兩者的比值才能說明該query篩選資料的能力。

 

3.掃描行數與訪問類型

explain 中的type列列出了訪問類型:全表掃;索引掃描;範圍掃描;單值查詢

 

6.3重構查詢的方式

 

6.3.1一個複雜的查詢還是多個簡單的查詢

由於mysql的網路通訊協定是‘半雙工’的,串連斷開的花費並不大,所以很多時候分解查詢是最佳化的sql的一個有效方式。

 

6.3.2切分查詢

切分查詢是指對大的查詢採取分而治之的策略,分時段分但伺服器端的壓力。但次執行分段的sql都是一樣的,只是通過do_query()返回的資料與limit實現對資料條目的分批處理。

 

6.3.3分解關聯查詢

將關聯查詢分解成多個sql步驟。

這樣做是減小事務的粒度,能夠緩解鎖的爭用,也能讓緩衝的資料更加模組化,便於使用緩衝。

 

6.4查詢的執行步驟

用戶端請求資料-->伺服器端查詢快取,命中返回,未命中-->mysql解析sql,先行編譯,產生執行計畫-->調用資料庫引擎api執行sql-->返回結果到用戶端

 

6.4.1mysql通訊協定

‘半雙工’。即同一時間,只有一方在發送資料,只有在接受完對方發送的資料,才可以向對方發出響應。

這裡提到了用戶端擷取資料的兩種方式,在c#一種是dateset,即一次性返回資料,在用戶端儲存資料快照(緩衝),一種dateread是保持用戶端與伺服器端的串連,用戶端隨時查詢資料。--不同的語言提供了不同的調用方式。

 

查詢狀態

指的是查詢的進程的執行狀態:需要注意的是sort result對結果集排序;sanding date表示自產生結果集或者在向用戶端返回資料。

6.4.2查詢快取

就是查詢步驟中的第二步查詢的結構。第七章中有介紹。

 

6.4.3查詢最佳化

即是查詢步驟中的第三步

 

1.語言解析器與前置處理器

解析器對文法進行檢查,前置處理器檢查語義並檢查使用者是否有許可權。

 

2.查詢最佳化工具

最佳化器對前置處理器產生的預先處理樹進行執行計畫的測算,計算各種執行計畫的花費(有前面的知識我們知道,這裡的花費往往指的是查詢需要訪問的資料頁的多少)

可以明白:最佳化器對成本的測算並不是啊完全準確的,但是對於大多數sql,io都是它的執行瓶頸所在。

注意最佳化器並不會考慮緩衝(有緩衝的話不應該第二步就命中,返回給用戶端了嗎。

 

最佳化有靜態最佳化與動態最佳化的區分,考慮到第七章查詢快取部分與預存程序的描述,我在考慮mysql是否儲存執行計畫呢?如何儲存sql的執行計畫的呢?靜態動態最佳化時二選一還是並存呢?

 

書中列出了10多中最佳化器能夠最佳化的查詢,我不在一一列舉。

 

  1. 資料索引的統計資訊

Myisam引擎儲存了count,而innodb只能提供估算值(innodb的資料與索引是糾纏的,插入刪除修改還可能導致頁分裂,頁合并等問題,所以儲存一個count之類的統計值維護不易)

 

4.關聯查詢的執行

Mysql的關聯查詢可以看做一個雙迴圈或者多迴圈,只有兩個表的關聯查詢,外側迴圈的表叫外表,內側迴圈的表叫內表。可以知道內側迴圈的查詢次數是遠多於外側的,所以內表非常需要一個合適的索引。

 

5.關聯查詢最佳化工具

但是內外表常常不是我們可以決定的,mysql最佳化器會在其中起作用,最佳化器會建立一顆深度優先樹,通過不同的組合得出花費最少的執行計畫。不過在關聯的表n過多時執行計畫樹的顆數會指數上升,n超過optimizer_search_depth就不再使用窮舉的方式了,而是使用別的搜尋方式擷取最優執行計畫。

 

上一段中mysql對關聯查詢的執行方式是嵌套迴圈,執行計畫表現為一顆深度優先樹。

 

  1. 排序最佳化

第三章中介紹了索引排序,這裡介紹filesort。

Filesort檔案排序,filesort並不總是要用到磁碟,當資料量較小時可以再記憶體中進行。

資料量是否大於檔案緩衝區是兩者的分水嶺。當使用磁碟排序是相當於外排序。

 

Mysql filesort排序策略

兩次讀取資料(舊版):只使用行指標與排序欄位做排序,這樣排序結果需要通過行指標才能讀取到全部資料,由於是隨機io,io效率低。

 

單次讀取資料(新版):先讀取所需要的列,然後在根據給定列進行排序。

兩個各有優劣,這個討論我們放在第8章中

5.6版本在這裡做出了改進,當使用limit時,mysql不再對所有結果排序,而是僅對需要的資料排序。

 

6.4.4查詢執行引擎

Mysql的執行計畫是一個資料結構,執行該執行計畫時,需要調用儲存引擎是響應的‘handler api’實現。如果是所有預存程序共有的特性,一般是伺服器層實現的,如日期函數,視圖,觸發器。

 

6.4.5返回資料

Mysql執行sql過程中,開始產生第一條結果時就開始返回資料,這樣是的伺服器不需要儲存大量的結果。(往後看可以發現union會到這個需要建立一個暫存資料表來儲存資料,前部union段執行完成才能返回資料)

高效能mysql 第六章查詢效能最佳化 總結(上)查詢的執行過程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.