1. 程式人生 > 其它 >切分查詢和分解關聯查詢和查詢基礎

切分查詢和分解關聯查詢和查詢基礎

採用分治思想,將大查詢切分成小查詢

比如將大資料量的刪除分批進行

分解關聯查詢優勢

  • 快取效率更高,拆分後如果某個表很少改變,基於該表的查詢就可以重複利用查詢快取結果了
  • 將查詢分解後,執行單個查詢可以減少鎖的競爭
  • 在應用層做關聯,容易對資料庫拆分
  • 查詢本身效率有所提升
  • 減少冗餘記錄的查詢,在應用層關聯查詢意味著對於某條記錄只需要查詢一次,在資料庫關聯查詢,可能需要重複訪問一部分資料
  • 在應用中使用雜湊關聯效率更高

查詢執行的基礎

MySQL客戶端和伺服器之間的通訊協議是半雙工(兩個人做拋球遊戲)

客戶端從伺服器取資料時,看起來是一個拉資料的過程,實際上是MySQL向客戶端推送資料的過程(從消防管喝水)

MySQL通常需要等所有的資料都已經發送給客戶端才能釋放這條查詢所佔用的資源,庫函式會快取全部資源

查詢狀態

show full proceslist
  • Sleep,執行緒等待客戶端傳送新請求
  • Query,執行緒正在執行查詢或者將結果傳送給客戶端
  • Locked,在MySQL服務層,執行緒等待表鎖;儲存引擎級別的鎖不會體現
  • Analyzing and statistics,執行緒正在收集儲存引擎的統計資訊,生成查詢的執行計劃
  • Copying to tmp table,GROUP BY、檔案排序或者是UNION操作後
  • Sorting result
  • Sending data

查詢快取

通過一個對大小寫敏感的雜湊查詢

查詢優化處理

將一個SQL轉換成一個執行計劃,MySQL按照這個計劃和儲存引擎進行互動

語法解析器和預處理

MySQL 通過關鍵字解析SQL語句,生成一棵解析樹,MySQL解析器用語法規則驗證和解析查詢

查詢優化器

當前查詢成本

show status like 'Last_query_cost'

導致MySQL優化器選擇錯誤的執行計劃

統計資訊不準確,MySQL 依賴儲存引擎提供的統計資訊評估成本

執行計劃中成本估算不等同於實際執行的成本

靜態優化(編譯時優化)

  • 直接對解析樹分析完成優化
  • 不依賴於特定數值,在第一次完成後一直有效

動態優化(與查詢上下文有關,執行時優化)

  • WHERE 條件取值,索引中條目對應的資料行數
  • 每次查詢都要重新評估

優化型別

重新定義關聯表的順序

資料表的關聯不總是按照在查詢中指定的順序進行

將外連線轉換為內連線

通過 WHERE 條件、庫表結構讓外連線等價於一個內連線

使用等價變換規則

儘量使用常量,合併和減少一些比較,移除恆成立和恆不成立

優化COUNT、MIN、MAX

要找到某一些最小值,只需要查詢對應B-Tree索引最左端的記錄

如果要查詢一個最大值,只需要讀取B-Tree索引的最後一條記錄

在 explain 中的 Extra 有Select tables optimized away 字樣

它表示優化器已經從執行計劃中移除了該表,並以一個常數代替

預估表示式轉換為常數

  • 使用者自定義變數在查詢中沒有發生變化可以轉換為一個常數
  • 在優化階段,若 WHERE 子句中使用了索引的常數條件,查詢開始階段先查詢這些值,優化器將表示式轉換為常數
  • 等式將常數值從一個表傳遞到另一個表,通過 using、where 或 on 限制某列取值為常量

覆蓋索引

自查詢優化

提前終止查詢

  • 使用limit
  • 使用 dinsinct、not exist 或者 left join

等值傳播

如果兩個列的值通過等式關聯,MySQL 把其中一列的 WHERE 條件傳遞到另一列上

select table1.id from table1 inner join db2.table2 using(id) where table1.id > 500;

這裡通過 id 欄位等值關聯,where 條件對兩個表都適用

列表IN的比較

MySQL 將 IN 列表中資料先進行排序,然後通過二分查詢確定列表中的值是否滿足條件,複雜度O(log n)

論讀書
睜開眼,書在面前
閉上眼,書在心裡