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

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

1. MySQL的客戶端/伺服器通信協議 1.1. MySQL的客戶端和伺服器之間的通信協議是“半雙工”的 1.2. 在任何時刻,要麼是由伺服器向客戶端發送數據,要麼是由客戶端向伺服器發送數據,這兩個動作不能同時發生 1.3. 當查詢的語句很長的時候,參數max_allowed_packet就特別重 ...


1. MySQL的客戶端/伺服器通信協議

1.1. MySQL的客戶端和伺服器之間的通信協議是“半雙工”的

1.2. 在任何時刻,要麼是由伺服器向客戶端發送數據,要麼是由客戶端向伺服器發送數據,這兩個動作不能同時發生

1.3. 當查詢的語句很長的時候,參數max_allowed_packet就特別重要了

1.4. 一般的伺服器響應給用戶的數據通常很多,由多個數據包組成

1.5. 當伺服器開始響應客戶端請求時,客戶端必須完整地接收整個返回結果,而不能簡單地只取前面幾條結果,然後讓伺服器停止發送數據

1.5.1. 在必要的時候一定要在查詢中加上LIMIT限制

1.6. 當客戶端從伺服器取數據時,看起來是一個拉數據的過程,但實際上是MySQL在向客戶端推送數據的過程

1.7. MySQL通常需要等所有的數據都已經發送給客戶端才能釋放這條查詢所占用的資源,所以接收全部結果並緩存通常可以減少伺服器的壓力,讓查詢能夠早點結束、早點釋放相應的資源

1.8. 當使用多數連接MySQL的庫函數從MySQL獲取數據時,其結果看起來都像是從MySQL伺服器獲取數據,而實際上都是從這個庫函數的緩存獲取數據

1.9. 如果能夠儘早開始處理這些結果集,就能大大減少記憶體的消耗,在這種情況下可以不使用緩存來記錄結果而是直接處理

1.9.1. 對於伺服器來說,需要查詢完成後才能釋放資源,所以在和客戶端交互的整個過程中,伺服器的資源都是被這個查詢所占用的

1.9.2. 用mysql_unbuffered_query()代替mysql_query(),PHP則不會緩存結果

2. SHOW FULL PROCESSLIST命令

2.1. 該命令返回結果中的Command列,其就表示當前的狀態

2.2. Sleep

2.2.1. 線程正在等待客戶端發送新的請求

2.3. Query

2.3.1. 線程正在執行查詢或者正在將結果發送給客戶端

2.4. Locked

2.4.1. 在MySQL伺服器層,該線程正在等待表鎖

2.5. Analyzing and statistics

2.5.1. 線程正在檢查存儲引擎的統計信息,並優化查詢

2.6. Copying to tmp table [on disk]

2.6.1. 線程正在執行查詢,並且將其結果集複製到一個臨時表中

2.6.2. 麽是在做GROUP BY操作

2.6.3. 要麼是在進行文件排序操作

2.6.4. 或者是在進行UNION操作

2.6.5. “on disk”標記,那表示MySQL正在將一個記憶體臨時表放到磁碟上

2.7. Sorting result

2.7.1. 線程正在對結果集進行排序

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

3.1. 統計信息不准確

3.1.1. MySQL伺服器依賴存儲引擎提供的統計信息來評估成本,但是有的存儲引擎提供的信息是準確的,有的偏差可能非常大

3.2. 成本指標並不完全等同於運行查詢的實際成本

3.3. MySQL的最優可能和你想的最優不一樣

3.3.1. MySQL只是基於其成本模型選擇最優的執行計劃,而有些時候這並不是最快的執行方式

3.4. MySQL從不考慮其他併發執行的查詢,這可能會影響到當前查詢的速度

3.5. MySQL也並不是任何時候都是基於成本的優化

3.5.1. 如果存在全文搜索的MATCH()子句,則在存在FULLTEXT索引的時候就使用全文索引

3.5.2. 即使有時候使用其他索引和WHERE條件可以遠比這種方式要快,MySQL也仍然會使用對應的全文索引

3.6. MySQL不會考慮不受其控制的操作的成本

3.6.1. 執行存儲函數或者用戶自定義函數的成本

4. 優化策略

4.1. 靜態優化

4.1.1. 不依賴於特別的數值

4.1.2. 在第一次完成後就一直有效,即使使用不同的參數重覆執行查詢也不會發生變化

4.1.3. 編譯時優化

4.2. 動態優化

4.2.1. 和查詢的上下文有關

4.2.2. 在每次查詢的時候都重新評估

4.2.3. 運行時優化

5. 優化類型

5.1. 重新定義聯接表的順序

5.1.1. 數據表的聯接並不總是按照在查詢中指定的順序進行

5.2. 將外聯接轉化成內聯接

5.2.1. 並不是所有的OUTER JOIN語句都必須以外聯接的方式執行

5.3. 使用代數等價變換規則

5.4. 優化COUNT()、MIN()和MAX()

5.4.1. 索引和列是否可為空通常可以幫助MySQL優化這類表達式

5.5. 預估並轉化為常數表達式

5.5.1. 當MySQL檢測到一個表達式可以轉化為常數的時候,就會一直把該表達式作為常數進行優化處理

5.6. 覆蓋索引掃描

5.6.1. 當索引中的列包含所有查詢中需要使用的列的時候,MySQL就可以使用索引返回需要的數據,而無須查詢對應的數據行

5.7. 子查詢優化

5.7.1. 將子查詢轉換為一種效率更高的形式,從而減少多個查詢多次對數據進行訪問

5.8. 提前終止查詢

5.8.1. 在發現已經滿足查詢需求的時候,MySQL總是能夠立刻終止查詢

5.8.2. 一個典型的例子就是當使用了LIMIT子句的時候

5.9. 類似這種“不同值/不存在”的優化一般可用於DISTINCT、NOT EXIST()或者LEFT JOIN類型的查詢

5.10. ⑩等值傳播

5.11. ⑾列表IN()的比較

5.11.1. IN()完全等同於多個OR條件的子句,因為這兩者是完全等價的

5.11.2. 在MySQL中這點是不成立的,MySQL將IN()列表中的數據先進行排序,然後通過二分查找的方式來確定列表中的值是否滿足條件,這是一個O(logn)複雜度的操作,等價地轉換成OR查詢的複雜度為O(n),對於IN()列表中有大量取值的時候,MySQL的處理速度將會更快

6. 表和索引的統計信息

6.1. 存儲引擎則給優化器提供對應的統計信息,包括:每個表或者索引有多少個頁面、每個表的每個索引的基數是多少、數據行和索引的長度是多少、索引的分佈信息等

7. 聯接查詢

7.1. MySQL對任何聯接都執行嵌套迴圈聯接操作,即MySQL先在一個表中迴圈取出單條數據,然後再嵌套迴圈到下一個表中尋找匹配的行,依次下去,直到找到所有表中匹配的行為止

7.2. 在MySQL 8.0.20版本之後,已經不再使用基於塊的嵌套迴圈聯接操作,取而代之的是哈希聯接

7.2.1. 這讓聯接操作性能變得更好,特別是當數據集可以全部存儲在記憶體時

7.3. 通常多表聯接的時候,可以有多種不同的聯接順序來獲得相同的執行結果

7.4. 執行計劃

7.4.1. 如果你對某個查詢執行EXPLAIN EXTENDED後,再執行SHOWWARNINGS,就可以看到重構出的查詢

7.5. 讓查詢進行更少的回溯和重讀操作

7.5.1. 可以使用STRAIGHT_JOIN關鍵字重寫查詢,讓優化器按照你認為的最優的聯接順序執行

7.6. n個表的聯接可能有n的階乘種聯接順序

7.6.1. 優化器選擇使用“貪婪”搜索的方式查找“最優”的聯接順序

7.6.2. 當需要聯接的表超過optimizer_search_depth的限制的時候,就會選擇“貪婪”搜索模式了

7.7. 查詢不能重新排序,聯接優化器可以利用這一點通過消除選擇來減小搜索空間


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

-Advertisement-
Play Games
更多相關文章
  • 有關mmd播放器,網上也有許多非常漂亮的實現,如 pmxeditor、saba、blender_mmd_tools等等。。 首先我想先介紹下我參考實現的倉庫: sselecirPyM/Coocoo3D: Experimental MMD renderer using DX12 and DXR. (g ...
  • 在我們設計軟體的很多地方,都看到需要對錶格數據進行導入和導出的操作,主要是方便客戶進行快速的數據處理和分享的功能,本篇隨筆介紹基於WPF實現DataGrid數據的導入和導出操作。 ...
  • 摘要:本智能化住宅防盜報警系統通過PLC以及組態監控實現了多種功能。系統可以自動控制和手動控制,在家人離開後啟動,在到達家後停止。當家裡沒有人時,系統會模擬有人居住的情況,通過設置燈光變換和排氣扇間斷工作來製造有人的情況。晚上通過設置燈光的變化來模擬生活的場景,白天的時候關閉燈光,晚上的時候打開卧室 ...
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他生產上的程式有記憶體暴漲情況,讓我幫忙看下怎麼回事,最簡單粗暴的方法就是讓朋友在記憶體暴漲的時候抓一個dump下來,看一看大概就知道咋回事了。 二:Windbg 分析 1. 到底是誰吃了記憶體 這個問題說的再多也不為過,一定要看清楚這個程式是如何個性化發展 ...
  • 前言 在構建API項目時,有時出於安全考慮,防止訪問用戶惡意攻擊,希望限制此用戶ip地址的請求次數,減輕拒絕服務攻擊可能性,也稱作限流。接下來,我們就來學習開源庫DotNetRateLimiter 如何輕鬆實現限流。 項目使用配置 安裝Nuget包 在新建立的WebAPI項目中,通過Nuget包管理 ...
  • 因為我本身沒有參與過項目架構,所以為了避免後續的開發過程中項目無序,繁雜。所以在這裡我要給我自己設定一個規範。 後端 目前採用的就是:Net6(長期支持)+倉儲模式(類似三層架構) 雖然現在流行微服務,但我目前還沒法自己完全去做,還得學啊! 目前8的預覽版已經出現,但是得申請,7的話是標準期限支持, ...
  • 可擴展性對於物聯網管理系統的設計和開發非常重要,它直接影響著系統的性能、可靠性和能耗等方面,是評估一個系統優劣的重要因素之一。可擴展性對物聯網管理系統的影響主要體現在以下幾個方面: ...
  • 引言 作為一名後端工程師,使用終端是一種常見的做法,也是你應該學習的技能。許多命令和實用程式可以幫助你在使用 Linux 時更有效地完成任務。 基本 Linux 命令 如果你想使用 Linux 操作系統,學習常用的命令將會大有幫助。本篇將為後端工程師回顧一些基本到高級的 Linux 操作命令。 基礎 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...