讀高性能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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...