低效查詢分析步驟
- 檢索大量超過需要的數據(訪問太多行或者列)
- 確認MYSQL服務器層是否在分析大量查過需要的數據
應用where條件
- 在索引中使用WHERE條件過濾不匹配的記錄,存儲引擎中完成
- 使用索引覆蓋掃描(Extra列中出現Using index)返回結果,直接從索引中過濾不需要的記錄並返回命中結果。MYSQL服務器層完成,無需回表
- 從數據表中返回數據,然後過濾不滿足條件的記錄(在Extra列中出現Using Where)。在MYSQL服務器層完成,MYSQL需要先從數據表讀出記錄然後過濾。
重構查詢方式
- 一個複雜查詢還是多個簡單查詢
- 切分查詢
- 分解關聯查詢
優勢:1.讓緩存效率更高
2.將查詢分解後,執行單個查詢可以減少鎖的競爭
3.在應用層做關聯,可以更容易對數據庫進行拆分,更容易做到高性能和可擴張
4.可以減少冗餘記錄的查詢
5.更進一步,這樣做相當於在應用中實現了哈希關聯,而不是使用MYSQL的嵌套循環關聯,某些場景下哈希關聯的效率要高很多
查詢執行基礎
- 客戶端發送一條查詢給服務器
- 服務器先檢查查詢緩存,如果命中了緩存,立刻返回存儲在緩存中的結果。否則進入下一階段
- 服務器端進行SQL解析、預處理,再由優化器生成對應的執行計劃
- MYSQL根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢
- 將結果返回給客戶端
MYSQL客戶端/服務器通信協議
-MYSQL客戶端和服務器之間的通信協議是半雙工(客戶端->服務端或服務端->客戶端同時只能有一個發生)
查詢狀態
對於一個MYSQL連接或者一個線程,任何時刻讀有一個狀態,該狀態表示了MYSQL當前正在做什麼。
查詢狀態命令: show full processlist
-
Sleep
線程正在等待客戶端發送新的請求 -
Query
線程正在執行查詢或者正在講結果發送給客戶端 -
Locked
在MYSQL服務器層,該線程在在等待表鎖或行鎖 -
Analyzing and statistics
線程正在收集存儲引擎的統計信息,並生成查詢的執行計劃 -
Sorting result
線程正在對結果集進行排序 -
Sending data
線程在多個狀態之間傳送數據,或者生成結果集,或者在向客戶端返回數據
獲得MySQL計算的當前查詢成本
select * from test;
show status like 'Last_query_cost'
MYSQL能夠處理的優化模型
-
重新定義關聯表的順序(笛卡爾積)
-
將外連接轉化爲內連接
-
使用等價變換規則(5==5 and a>5改寫爲a>5)
-
優化COUNT()、MIN()、MAX()
索引和列是否可爲空通常卡伊幫助MYSQL優化這類表達式 -
預估並轉化爲常數表達式
當MYSQL檢測到一個表達式可以轉換爲常數的是否,就會一直把該表達式作爲常數進行優化處理 -
覆蓋索引掃描
當索引中的列包含所有查詢中要使用的列的時候,MYSQL就可以使用索引返回需要的數據,而無需查詢對應的數據行 -
子查詢優化
MYSQL在某些情況下可以將子查詢轉換喲中效率更高的形式,從而減少多個查詢多次對數據進行訪問 -
提前終止查詢
在發現已經滿足查詢需求的時候,MYSQL總是能夠立刻終止查詢。(Limit) -
等值傳播
如果兩個列的值通過等式關聯,那麼MYSQL能夠把其中一個列的WHERE條件傳遞到另一列上
select film.film_id from sakila.filn inner join sakila.film_actor using(film_id) where film.film_id>500
這裏film_id字段進行等值關聯,MYSQL知道這裏的WHERE子句不僅適用於film表,而且對film_actor表同樣適用。
- 列表IN()的比較
在MYSQL中將IN()列表中的數據先進行排序然後通過二分查找的方式來確定列表中的值是否滿足條件,這是一個O(logn)複雜度的操作,等價地轉換成OR查詢的複雜度爲O(n),對於IN()列表中有大量取值的時候,MYSQL的處理速度將會更快