一、慢查詢優化語句
低效查詢的分析步驟:
1.確認程式是否存在檢索大量超過需要的資料。
2.確認伺服器層是否在分析大量的超出需要的資料行。
下面詳細描述一下這兩方面
1.1 是否查詢了大量不必要的資料
1.查詢不需要的資料
2.多表關聯時候返回全部列
3.總是取出全部列
在大部分場景不建議如此,會耗費大量的i/o、記憶體和cpu資源
4.重複查詢相同的資料
1.2 mysql是否在掃瞄額外的資料航
衡量查詢的三個指標:
響應時間,掃瞄行數,返回行數
響應時間
是服務時間(真正查詢的時間)和排隊時間(伺服器因為某些原因而等待沒有執行查詢的時間)之和,
掃瞄行數和返回的行數
掃瞄行數和返回行數比例一般在 1:1到10:1之間
掃瞄行數和訪問型別
訪問型別種類: 全表掃瞄、索引掃瞄、範圍查詢、唯一索引查詢和常數引用查詢。
從前到後速度從慢到塊,掃瞄行數從小到大
mysql的三種應用where條件:
1.在索引中使用where條件過濾不匹配資料,在儲存引擎中完成
2.使用索引覆蓋掃瞄過濾不需要的資料,在服務層完成,不需要回表
3.從資料表中返回資料,然後過濾不需要的資料,在服務層完成,mysql需要先從資料表中讀出記錄然後過濾。
二、重構查詢的方式
1.在不同的場景下,乙個複雜sql還是選擇拆分多個簡單sql要根據情況選擇
2.切分查詢
例如刪除海量的資料可以拆分成多次少量資料的刪除,可以省去mysql的資源而不影響業務,用時間換空間,大大降低對伺服器的影響。
3.分解關聯查詢
將多表關聯的sql語句差分成多個單錶查詢,有如下優點:
可以高效的利用快取
執行單個查詢減少鎖的競爭
在業務層面做表的關聯,易於資料庫的拓展
查詢本身效率提高
減少冗餘記錄的查詢
最後,這樣實際上是在應用中實現了雜湊關聯,而不是mysqlde巢狀迴圈關聯,某些場景下,效率更高。
三、執行查詢的基礎
一條查詢語句的執行流程:
[1]客戶端傳送一條查詢語句給客戶端
[2]查詢快取,如果命中,返回結果,否則進入下一階段。
[3]伺服器端進行sql解析,預處理,再由優化器生成對應的執行計畫
[4]mysql根據優化器生成的執行計畫,呼叫儲存引擎的api執行查詢
[5]將結果返回給客戶端
3.1mysql的客戶端和服務端的通訊協議
mysql的客戶端和服務端的通訊協議是"半雙工的",意味著在某一時刻,伺服器向客戶端傳送資料和客戶端向伺服器傳送資料只能發生乙個,不會同時發生。
一般來說查詢的結果會放到快取中後再返回給客戶端,這就需要注意返回的結果資料集不能過於龐大,可能導致所有的資源都被這乙個查詢所占用。
3.2查詢快取
在解析乙個查詢語句前,如果查詢快取是開啟的,那麼mysql會優先查詢是否會命中快取中的資料,如果命中,就返回結果,而不會解析sql語句生成執行計畫。
3.3解析器和預處理
mysql通過關鍵字將sql語句進行解析,生成對應的"解析樹"。mysql解析器使用mysql語法規則驗證和解析查詢。
預處理器根據mysql規則驗證生成的解析樹是否合法,進而驗證許可權。
解析書驗證合法,下一步優化器將其轉為執行計畫。mysql使用基於成本的優化器,會嘗試**使用一種執行計畫的成本選擇最小的成本的計畫。
導致mysql選擇錯誤的執行計畫的因素:
統計資訊不準確。
執行計畫中的成本不等於實際執行的成本。
mysql對於最優的定義和開發者的理解會有偏差。
mysql從不考慮其他併發執行的查詢。
mysql不是任何時候都是基於成本的優化。
不會考慮不受其控制的成本。
無法估算所有可能的執行計畫。
3.4優化器
mysql的優化器有兩種:靜態優化和動態優化。
靜態優化:可以直接對解析樹進行分析完成優化,不依賴特別的數值,在第一次優化完成後一直有效,即使使用不同的引數重複查詢也不會變化,是一種"編譯時優化"。
動態優化:與查詢上下文有關,對查詢的動態優化每次執行時都會重新評估。
mysql能夠處理的優化型別有:
重新定義關聯表的順序
將外連線轉為內連線
使用等價變換規則
優化count()、min()、max()
預估並轉為常數表示式
覆蓋索引掃瞄
子查詢優化
提前終止查詢
列表in()的比較
當前mysql的關聯執行策略:對任何關聯都執行巢狀迴圈關聯操作。
3.5執行計畫
mysql生成查詢指令樹,通過儲存引擎執行這個指令樹返回結果,最後的執行計畫包含重構查詢的全部計畫。
關聯查詢優化器:決定多個表的關聯順序,關聯優化查詢器通過評估不同順序時的成本選擇代價最小的關聯順序。
排序優化:排序是很高的操作,從效能上來說盡量避免使用排序操作。需要排序資料量小於"排序緩衝區"則在記憶體排序,記憶體不夠則會先將資料分塊,並將各個塊的排序結果存放在磁碟上,然後將各個排好序的塊合併,返回結果,會使用磁碟,mysql將這個過程統一稱為檔案排序,即使是僅使用記憶體排序。
mysql兩種排序演算法:
兩次傳輸排序(舊版本使用):讀取指標和需要排序的字段,進行排序,根據排序結果讀取需要的資料行
單次排序使用(新版本使用):mysql4.1及以後的版本引入此演算法。讀取查詢需要的所有列,根據給定列排序,返回排序結果。
單次排序的優點是只需一次順序i/o讀取所有資料,無需任何的隨機i/o,缺點是需要返回的列多非常大會很占用空間。
mysql進行檔案排序使用的臨時儲存空間比想象的要大,因為mysql在排序時,對每個排序揭露都會分配乙個足夠長的定長空間來存放。定長空間必須足夠長以容納其中最長的字串。
查詢執行引擎:根據自執行計畫完成整個查詢,在執行計畫逐步執行的過程中會大量的呼叫儲存引擎實現的介面來完成,這些介面又稱為"handler api"。
3.6 返回結果給客戶端
是乙個增量逐步返回的過程
四、mysql查詢優化器的侷限性
4.1關聯子查詢
4.2union的限制
4.3等值傳遞
4.4並行執行
4.5雜湊關聯
4.6鬆散索引掃瞄
4.7最大值和最小值優化
4.8在同乙個表上查詢和優化
五、查詢優化器的提示
如果對執行計畫不滿意,可以使用優化器提供的幾個提示來控制最終的執行計畫。
六、優化特定型別的查詢
6.1優化count()查詢
統計某個列值的數量也可以統計行數。
對於myisam的誤解:count()函式極其的快,是有前提條件的,即不能有where條件才會快。
簡單的優化
使用近似值,結合實際業務場景考慮
更複雜的優化,考慮使用快取
6.2優化關聯查詢
確保on或using子句中的列上有索引。
確保order by 和 group by 的表示式只設計乙個表中的列。
當公升級mysql的時候要注意:關聯語法、運算子優先順序等可能發生改變的地方
6.3優化子查詢
截止目前的mysql版本,建議盡量使用關聯查詢代替
6.4優化group by 和 distinct
mysql無法使用索引時候,group by 使用兩種策略:使用臨時表或檔案排序來做分組。
使用group by with rollup,即對返回的結果再次的分組。
6.5優化limit分頁
儘量減少掃瞄的行數,可以使用覆蓋索引優化
6.6優化sql_calc_foundp_rows
使用分頁模糊設計和快取優化
6.7優化union查詢
除非必要去重,否則盡量使用union all,mysql會給臨時表加個distinct選項,導致對整個臨時表的資料做唯一性檢查,代價很高。
6.8靜態查詢分析
6.8使用使用者自定義變數
是乙個用來儲存內容的臨時容器。
以下場景補鞥呢使用:
使用自定義變數查詢,無法使用查詢快取。
不能在使用常量或識別符號的地方使用,例如表名,列名和limit子句中。
如果使用連線池或持久化連線,自定義可能讓看起來毫無關係的**發生互動。
相容性問題。
不能顯式的宣告自定義變數的型別。
在某些場景自定義變數可能被優化掉。
賦值的順序和時間點不固定,依賴優化器的決定。
賦值符號 := 的優先順序很低
使用未定義變數不會產生任何語法錯誤。
總結:自定義變數使用門檻較高,需要較深的研究才可以使用,如果不太擅長,盡量避免使用自定義變數。
高效能MySQL讀書筆記(第六章上)
查詢為什麼會慢 重構查詢的方法 重要 我們覺得查詢慢的時候就要開始考慮優化了,那麼 慢 是怎麼理解呢?當乙個查詢任務超過了我們能忍受的時間,就是 慢 了,我們就要考慮下優化。前面我們學習了索引優化 庫表結構優化,下面我們一步步看查詢優化。乙個查詢相當於服務端的乙個任務,從開始到結束是乙個完整生命週期...
高效能MySQL 第六章
查詢優化 索引優化 庫表結構優化 優化查詢嗎,實際上是優化其子任務。優化查詢 1。消除子任務 2。減少子任務執行次數 3。讓子任務執行的更快 查詢效能低下最基本的原因是訪問的資料太多。1 返回的結果 limit,避免返回不需要的資料 而不是返回全部結果集 select 是否需要返回全部列?2 掃瞄的...
第六章讀書筆記
linux系統將每個驅動都對映成乙個檔案,這些檔案稱為裝置檔案或驅動檔案,都儲存在 dev目錄中。編寫linux驅動程式的步驟 第1 步 建立linu x 驅動骨架 裝載和解除安裝linu x 驅動 第2 步 註冊和登出裝置檔案 第3 步z 指定與驅動相關的資訊 第4 步 指定 函式 第5 步z 編...