MySQL進階實戰7,查詢的執行過程
@
目錄一、拆分查詢
將大查詢拆分成小查詢,每個查詢功能完全一樣,只是一小部分,每次只返回一小部分查詢結果。
比如在刪除舊資料的時候,如果用一個大的語句一次性刪的話,則可能需要一次性鎖住很多資料、佔滿整個事務日誌、耗盡系統資源、阻塞其它查詢任務。如果將一個大的刪除語句拆分成若干個較小的刪除語句,可以提升MySQL的效能。一次刪除一萬行資料一般來說是一個比較高效並且對伺服器影響最小的做法。
二、分解關聯查詢
分解關聯查詢的優勢
- 讓快取更高效,如果某個表改變了,就無法使用查詢快取了,而拆分後,如果其它表沒變化,那麼基於這些表的查詢就可以使用快取結果了;
- 將查詢分解後,執行單表查詢時可以減少鎖的競爭;
- 在應用層做關聯,可以更容易對資料進行拆分,更容易做到高效能和高擴充套件;
- 查詢本身的效率也可能會提升;
- 可以減少冗餘記錄的查詢
三、查詢的執行過程
-
客戶端傳送一條查詢語句到伺服器
-
伺服器先查詢快取,如果命中快取,則立即返回儲存在快取中的資料;
-
未命中快取後,MySQL通過關鍵字將SQL語句進行解析,並生成一顆對應的解析樹,MySQL解析器將使用MySQL語法進行驗證和解析。例如,驗證是否使用了錯誤的關鍵字,或者關鍵字的使用是否正確;
-
預處理是根據一些MySQL規則檢查解析樹是否合理,比如檢查表和列是否存在,還會解析名字和別名,然後前處理器會驗證許可權;
-
根據執行計劃查詢執行引擎,呼叫API介面呼叫儲存引擎來查詢資料;
-
將結果返回客戶端,並進行快取;
多數連線MySQL的庫函式都可以獲得全部結果集並快取在記憶體中,還可以逐行獲取需要的資料。預設一般是獲得全部結果集並快取到記憶體中。MySQL通常需要等所有的資料都已經發送給客戶端才能釋放這條查詢所佔用的資源,所以接收全部結果並快取通常可以減少伺服器的壓力,讓查詢能夠早點結束,早點釋放相應的資源。
四、優化器的一些優化手段
1、重新定義關聯表的順序
資料庫的關聯並不總是按照查詢中指定的順序進行,優化器可能會改變其關聯順序,生成最優的執行計劃。
2、將外連線轉化為內連線
3、使用增加變換規則
4、優化count()、max()、min()
如果使用min()獲取最小值時,可以查詢B-Tree索引最左端的記錄,MySQL可以直接獲取索引的第一行記錄。優化器會將這個表示式作為一個常數對待,max()也是如此。如果MySQL使用了這個型別的優化,在explain時就會看到“select tables optimized away”
。它表示優化器已經從執行計劃中移除了該表,並通過一個常量取而代之。
5、預估並轉化為常量表達式
當MySQL檢測到一個表示式可以轉化為常數的時候,就會一直將該表示式作為常量進行優化處理。
6、覆蓋索引掃描
當索引中的列包含所有查詢中需要使用的列時,MySQL就可以使用索引返回需要的資料,而無須查詢對應的資料行。
7、提前終止查詢
可以通過limit主動終止查詢。
五、MySQL如何執行關聯查詢
MySQL對任何關聯都執行巢狀迴圈關聯操作,即MySQL先在一個表中迴圈取出單條資料,然後再巢狀迴圈到下一個表中尋找匹配的行,依次下去,直到找到所有表中匹配的行為止。然後根據各個表匹配的行,返回查詢需要的各個列。
六、查詢執行引擎
在解析和優化階段,MySQL將生成查詢對應的執行計劃,MySQL的查詢執行引擎則根據這個執行計劃來完成整個查詢。這裡的執行計劃是一個數據結構,而不是像很多其他資料庫那樣會生成對應的位元組碼。
查詢執行階段,只是簡單地根據執行計劃給出的指令逐步執行。在根據執行計劃逐步執行的過程中,有大量的操作需要通過呼叫儲存引擎實現的介面來完成,這些即可被稱為“handler API”
。
MySQL在優化階段就會為每個表建立一個handler例項,優化器根據這些例項的介面可以獲取表的相關資訊,包括表的所有列名、索引統計資訊等。
七、分頁
做法1:假設每頁顯示10條記錄,那麼每次查詢時用limit返回11條記錄,並顯示其中的10條,如果第11條存在,那麼就顯示下一頁按鈕,否則就說明沒有更多的資料。
做法2:現貨區並快取較多的資料,比如先查詢1000行,然後每次分頁都從這個快取中獲取,如果結果集小於1000,就可以在頁面上顯示所有的分頁連結,因為資料在快取中,這樣做效能不會出現問題。如果結果集大於1000,則可以在頁面上加一個查詢更多資料的按鈕。
這兩種方式逗比每次獲取全部結果集,再拋棄不需要的資料的方式效率高。