讀高性能MySQL(第4版)筆記10_查詢性能優化(上)

来源:https://www.cnblogs.com/lying7/archive/2023/09/19/17710002.html
-Advertisement-
Play Games

1. 三管齊下 1.1. 不做、少做、快速地做 1.2. 如果查詢太大,服務端會拒絕接收更多的數據並拋出相應錯誤 1.3. 如果查詢寫得很糟糕,即使庫表結構再合理、索引再合適,也無法實現高性能 1.4. 查詢優化、索引優化、庫表結構優化需要齊頭併進,一個不落 1.5. Percona Toolkit ...


1. 三管齊下

1.1. 不做、少做、快速地做

1.2. 如果查詢太大,服務端會拒絕接收更多的數據並拋出相應錯誤

1.3. 如果查詢寫得很糟糕,即使庫表結構再合理、索引再合適,也無法實現高性能

1.4. 查詢優化、索引優化、庫表結構優化需要齊頭併進,一個不落

1.5. Percona Toolkit中的pt-archiver工具

2. 響應時間

2.1. 如果把查詢看作一個任務,那麼它由一系列子任務組成,每個子任務都會消耗一定的時間

2.2. 如果要優化查詢,實際上要優化其子任務,要麼消除其中一些子任務,要麼減少子任務的執行次數,要麼讓子任務運行得更快

2.3. 優化查詢的目的就是減少和消除這些操作所花費的時間

2.4. 查詢需要在不同的地方花費時間

2.4.1. 網路、CPU計算、生成統計信息和執行計劃、鎖等待(互斥等待)等操作

2.4.2. 尤其是向底層存儲引擎檢索數據的調用操作,這些調用需要在記憶體操作、CPU操作和記憶體不足時導致的I/O操作上消耗時間

2.5. 兩部分之和:服務時間和排隊時間

2.5.1. 服務時間是指資料庫處理這個查詢真正花了多長時間

2.5.2. 排隊時間是指伺服器因為等待某些資源而沒有真正執行查詢的時間——可能是等I/O操作完成,也可能是等待行鎖

2.6. 響應時間既可能是一個問題的結果也可能是一個問題的原因,不同案例情況不同

2.7. 實際上可以使用“快速上限估計”法來估算查詢的響應時間

2.7.1. 瞭解這個查詢需要哪些索引以及它的執行計劃是什麼

2.7.2. 計算大概需要多少個順序和隨機I/O

2.7.3. 用其乘以在具體硬體條件下一次I/O的消耗時間

2.7.4. 把這些消耗都加起來

2.7.5. 獲得一個大概參考值來判斷當前響應時間是不是一個合理的值

3. 查詢的生命周期

3.1. 從客戶端到伺服器,然後在伺服器上進行語法解析,生成執行計劃,執行,並給客戶端返回結果

3.2. “執行”可以被認為是整個生命周期中最重要的階段

4. 優化數據訪問

4.1. 如果性能很差,最常見的原因是訪問的數據太多

4.2. 是否在檢索大量且不必要的數據

4.2.1. 訪問了太多的行

4.2.2. 訪問了太多的列

4.3. 確認MySQL伺服器層是否在分析大量不需要的數據行

4.3.1. 會請求超過實際需要的數據,然後這些多餘的數據會被應用程式丟棄

4.3.2. 消耗應用伺服器的CPU和記憶體資源

4.4. 一個常見的錯誤是,常常會誤以為MySQL只會返回需要的數據,實際上MySQL卻是先返回全部結果集再進行計算

4.4.1. 最簡單有效的解決方法就是在這樣的查詢後面加上LIMIT子句

4.5. 每次看到SELECT*的時候都需要用懷疑的眼光審視,是不是真的需要返回全部的列,很可能不是必需的

4.5.1. 取出全部列,會讓優化器無法完成索引覆蓋掃描這類優化

4.5.2. 嚴格禁止SELECT*的寫法,這樣做有時候還能避免某些列被修改而帶來的問題

4.6. 查詢返回超過需要的數據也不總是壞事

4.7. 重覆查詢相同的數據

4.7.1. 當初次查詢的時候將這個數據緩存起來,需要的時候從緩存中取出,這樣性能顯然會更好

4.8. 檢查慢日誌記錄是找出掃描行數過多的查詢的好辦法

4.9. 掃描的行數和返回的行數

4.9.1. 查看該查詢掃描的行數能夠說明該查詢找到需要的數據的效率高不高

4.9.2. 理想情況下掃描的行數和返回的行數應該是相同的,但實際中這種“美事”並不多

4.9.3. 掃描的行數與返回的行數的比率通常很低,一般在1:1到10:1之間,不過有時候這個值也可能非常非常大

4.10. 訪問類型有很多種,從全表掃描到索引掃描、範圍掃描、唯一索引查詢、常數引用等

4.10.1. 訪問方式可能無須掃描就能返回結果

4.10.2. 訪問方式可能需要掃描很多行才能返回一行結果

4.10.3. 沒辦法找到合適的訪問類型,那麼最好的解決辦法通常就是增加一個合適的索引

4.11. 應用WHERE條件

4.11.1. 在索引中使用WHERE條件來過濾不匹配的記錄

4.11.1.1. 在存儲引擎層完成的

4.11.2. 使用索引覆蓋掃描(在Extra列中出現了Using index)來返回記錄

4.11.2.1. 直接從索引中過濾不需要的記錄並返回命中的結

4.11.2.2. 在MySQL伺服器層完成的,但無須再回表查詢記錄

4.11.3. 從數據表中返回數據,然後過濾不滿足條件的記錄(在Extra列中出現Using where)

4.11.3.1. 在MySQL伺服器層完成

4.11.3.2. 需要先從數據表中讀出記錄然後過濾

4.12. 不是說增加索引就能讓掃描的行數等於返回的行數

4.13. 優化

4.13.1. 使用索引覆蓋掃描,把所有需要用的列都放到索引中,這樣存儲引擎無須回表獲取對應行就可以返回結果了

4.13.2. 改變庫表結構

4.13.2.1. 使用單獨的彙總表

4.13.3. 重寫這個複雜的查詢,讓MySQL優化器能夠以更優化的方式執行

5. 重構查詢的方式

5.1. 在優化有問題的查詢時,目標應該是找到獲得實際需要的結果的替代方法

5.1.1. 但這並不一定意味著從MySQL返回完全相同的結果集

5.1.2. 可以將查詢轉換為返回相同結果的等價形式,以獲得更好的性能

5.2. 以前人們總是認為網路通信、查詢解析和優化是一件代價很高的事情

5.2.1. 對於MySQL並不適用

5.2.2. MySQL從設計上讓連接和斷開連接都很輕量,在返回一個小的查詢結果方面很高效

5.2.3. 現代的網路速度比以前要快很多,能在很大程度上降低延遲

5.3. 在MySQL內部,每秒能夠掃描記憶體中上百萬行的數據

5.3.1. MySQL響應數據給客戶端就慢得多了

5.4. 在其他條件都相同的時候,使用儘可能少的查詢當然是更好的

5.4.1. 將一個大查詢分解為多個小查詢是很有必要的

5.4.2. 如果在一個查詢能夠勝任時還將其寫成多個獨立的查詢是不明智的

5.5. 切分查詢

5.5.1. 刪除舊的數據就是一個很好的例子

5.5.1.1. 定期清除大量數據時,如果用一個大的語句一次性完成的話,則可能需要一次鎖住很多數據、占滿整個事務日誌、耗盡系統資源、阻塞很多小的但重要的查詢

5.5.1.2. 將一個大的DELETE語句切分成多個較小的查詢可以儘可能小地影響MySQL的性能,同時還可以降低MySQL複製的延遲

5.5.2. 一次刪除一萬行數據一般來說是一個比較高效而且對伺服器影響最小的做法(如果是事務型引擎,很多時候小事務能夠更高效)

5.5.3. 如果每次刪除數據後,都暫停一會兒再做下一次刪除,也可以將伺服器上原本一次性的壓力分散到一個很長的時間段中,可以大大降低對伺服器的影響,還可以大大減少刪除時鎖的持有時間

5.6. 分解聯接查詢

5.6.1. 很多高性能的應用都會對聯接查詢進行分解

5.6.2. 可以對每一個表進行一次單表查詢,然後將結果在應用程式中進行聯接

5.6.3. 讓緩存的效率更高

5.6.4. 將查詢分解後,執行單個查詢可以減少鎖的競爭

5.6.5. 在應用層做聯接,可以更容易對資料庫進行拆分,更容易做到高性能和可擴展

5.6.6. 查詢本身的效率也可能會有所提升

5.6.6.1. 使用IN()代替聯接查詢,可以讓MySQL按照ID順序進行查詢,這可能比隨機的聯接要更高效

5.6.7. 可以減少對冗餘記錄的訪問

5.6.7.1. 在應用層做聯接查詢,意味著對於某條記錄應用只需要查詢一次,而在資料庫中做聯接查詢,則可能需要重覆地訪問一部分數據


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 現代軟體應用很少獨立工作。典型的應用程式會與幾個外部系統進行通信,如: 資料庫、 消息系統、 緩存提供商 其他第三方服務。 你應該編寫測試確保一切正常運行。 單元測試有助於隔離地測試業務邏輯,不涉及任何外部服務。它們易於編寫並提供幾乎即時的反饋。 有了單元測試還不夠,集成測試用來驗證與外部系統的交互 ...
  • 創建C#項目且使用.Net6.0以上的版本時,預設code會使用頂級語句形式: 1、略去static void Main(String[ ] args)主方法入口; 2、隱式使用(即隱藏且根據代碼所需要的類自動調用)其他命名空間(包括): using System; using System.IO; ...
  • 當使用LINQ查詢數據時,我們常常會面臨選擇使用.AsEnumerable(), .AsQueryable(), 和 .ToList()方法的情況。這些方法在使用時有不同的效果和影響,需要根據具體場景來選擇合適的方法 .AsEnumerable()方法: 使用.AsEnumerable()方法可以將 ...
  • 本文詳細介紹了前端請求參數加密、.NET 後端解密,文章較長,請各位看官耐心看完。 目錄一、前端使用“CryptoJS”,前端AES加密,.NET後端AES解密1.1、加密解密效果圖1.2、CryptoJS介紹1.3、準備工作:安裝“CryptoJS”1.3.1、使用npm進行安裝1.3.2、Vis ...
  • 目錄前言NPOI簡介一、安裝相對應的程式包1.1、在 “管理NuGet程式包” 中的瀏覽搜索:“NPOI”二、新建Excel幫助類三、調用3.1、增加一個“keywords”模型類,用作導出3.2、添加一個控制器3.3、編寫導入導出的控制器代碼3.3.1、重寫“Close”函數3.3.2、添加控制器 ...
  • 1、下載相關安裝包 CentOS-7 所有rpm包的倉庫地址:http://mirror.centos.org/centos/7/os/x86_64/Packages/ perl-5.16.3-297.el7.x86_64.rpm快速下載地址: http://mirror.centos.org/ce ...
  • 本文基於內核 5.4 版本源碼討論 之前有不少讀者給筆者留言,希望筆者寫一篇文章介紹下 mmap 記憶體映射相關的知識體系,之所以遲遲沒有動筆,是因為 mmap 這個系統調用看上去簡單,實際上並不簡單,可以說是非常複雜的一個系統調用。 如果想要給大家把 mmap 背後的技術本質,正確地,清晰地還原出來 ...
  • 痞子衡嵌入式半月刊: 第 80 期 這裡分享嵌入式領域有用有趣的項目/工具以及一些熱點新聞,農曆年分二十四節氣,希望在每個交節之日準時發佈一期。 本期刊是開源項目(GitHub: JayHeng/pzh-mcu-bi-weekly),歡迎提交 issue,投稿或推薦你知道的嵌入式那些事兒。 上期回顧 ...
一周排行
    -Advertisement-
    Play Games
  • WPF本身不支持直接的3D繪圖,但是它提供了一些用於實現3D效果的高級技術。 如果你想要在WPF中進行3D繪圖,你可以使用兩種主要的方法: WPF 3D:這是一種在WPF應用程式中創建3D圖形的方式。WPF 3D提供了一些基本的3D形狀(如立方體、球體和錐體)以及一些用於控制3D場景和對象的工具(如 ...
  • 一、XML概述 XML(可擴展標記語言)是一種用於描述數據的標記語言,旨在提供一種通用的方式來傳輸和存儲數據,特別是Web應用程式中經常使用的數據。XML並不預定義標記。因此,XML更加靈活,並且可以適用於廣泛的應用領域。 XML文檔由元素(element)、屬性(attribute)和內容(con ...
  • 從今年(2023)三月份開始,Github開始強制用戶開啟兩步驗證2FA(雙因數)登錄驗證,毫無疑問,是出於安全層面的考慮,畢竟Github賬號一旦被盜,所有代碼倉庫都會毀於一旦,關於雙因數登錄的必要性請參見:別讓你的伺服器(vps)淪為肉雞(ssh暴力破解),密鑰驗證、雙向因數登錄值得擁有。 雙因 ...
  • 第一題 下列代碼輸入什麼? public class Test { public static Test t1 = new Test(); { System.out.println("blockA"); } static { System.out.println("blockB"); } publi ...
  • 本文主要涉及的問題:用ElementTree和XPath讀寫XML文件;解決ElementTree新增元素後再寫入格式不統一的問題;QTableWidget單元格設置控制項 ...
  • QStandardItemModel 類作為標準模型,主打“類型通用”,前一篇水文中,老周還沒提到樹形結構的列表,本篇咱們就好好探討一下這貨。 還是老辦法,咱們先做示例,然後再聊知識點。下麵這個例子,使用 QTreeView 組件來顯示數據,使用的列表模型比較簡單,只有一列。 #include <Q ...
  • 一、直充內充(充值方式) 直充: 包裝套餐直接充值到上游API系統。【PID/Smart】 (如:支付寶、微信 話費/流量/語音/簡訊 等 充值系統)。 內充(套餐打包常見物聯卡系統功能): 套餐包裝 適用於不同類型套餐 如 流量、簡訊、語音 等。 (目前已完善流量邏輯) 二、套餐與計費產品 計費產 ...
  • 在前面幾天中,我們學習了Dart基礎語法、可迭代集合,它們是Flutter應用研發的基本功。今天,我們繼續學習Flutter應用另一個必須掌握知識點:非同步編程(即Future和async/await)。它類似於Java中的FutureTask、JavaScript中的Promise。它是後續Flut... ...
  • 針對改動範圍大、影響面廣的需求,我通常會問上線了最壞情況是什麼?應急預案是什麼?你帶開關了嗎?。當然開關也是有成本的,接下來本篇跟大家一起交流下高頻發佈支撐下的功能開關技術理論與實踐結合的點點滴滴。 ...
  • 1.d3.shuffle D3.shuffle() 方法用於將數組中的元素隨機排序。它使用 Fisher–Yates 洗牌演算法,該演算法是無偏的,具有最佳的漸近性能(線性時間和常數記憶體)。 D3.shuffle() 方法的語法如下: d3.shuffle(array, [start, end]) 其中 ...