MySQL SQL 優化專題

MySQL SQL 優化專題

1. 插入數據優化

-- 普通插入(不推薦)
INSERT INTO tb_user VALUES(1,'tom');
INSERT INTO tb_user VALUES(2,'cat');
INSERT INTO tb_user VALUES(3,'jerry');-- 優化方案1:批量插入(推薦,不建議超過1000條,500-1000較為合適)
INSERT INTO tb_user VALUES(1,'tom'), (2,'cat'), (3,'jerry');-- 優化方案2:手動事務提交(適用于大數據量)
start transaction;
INSERT INTO tb_user VALUES(1,'tom');
INSERT INTO tb_user VALUES(2,'cat');
commit;-- 優化方案3:主鍵順序插入(減少頁分裂)
-- 有序ID:1,2,3,4... 
-- 無序ID:3,1,4,2...-- 優化方案4:LOAD命令(百萬級數據)
-- 客戶端連接服務端時,加上參數  -–local-infile
mysql –-local-infile  -u  root  -p
-- 設置全局參數local_infile為1,開啟從本地加載文件導入數據的開關
set  global  local_infile = 1;
-- 執行load指令將準備好的數據,加載到表結構中
-- 語法:LOAD DATA LOCAL INFILE '文件路徑' INTO TABLE 表名; 
load  data  local  infile  '/root/sql1.log'  into  table  tb_user  fields  terminated  by  ','  lines  terminated  by  '\n' ; 

原理說明

  • 批量插入減少事務提交次數
  • 順序插入可減少頁分裂概率
  • LOAD指令比INSERT快約20倍

2. 主鍵優化

(1)數據組織方式

在InnoDB存儲引擎中,表數據都是根據主鍵順序組織存放的,這種存儲方式的表稱為索引組織表 (index organized table IOT)。

  • InnoDB采用B+樹索引,數據存儲在葉子節點
  • 頁分裂(離散插入導致)和頁合并(刪除數據后觸發)

在這里插入圖片描述

行數據,都是存儲在聚集索引的葉子節點上的。InnoDB的邏輯結構圖:

在這里插入圖片描述

在InnoDB引擎中,數據行是記錄在邏輯結構 page 頁中的,而每一個頁的大小是固定的,默認16K。 那也就意味著, 一個頁中所存儲的行也是有限的,如果插入的數據行row在該頁存儲不小,將會存儲 到下一個頁中,頁與頁之間會通過指針連接。

**(2). 頁分裂 **

頁可以為空,也可以填充一半,也可以填充100%。每個頁至少包含了2行數據(只有一行數據就等于退化成鏈表了)(如果一行數據過大,會行溢出),根據主鍵排列。

A. 主鍵順序插入效果

①. 從磁盤中申請頁, 主鍵順序插入

在這里插入圖片描述

②. 第一個頁沒有滿,繼續往第一頁插入

在這里插入圖片描述

③. 當第一個也寫滿之后,再寫入第二個頁,頁與頁之間會通過指針連接

在這里插入圖片描述

④. 當第二頁寫滿了,再往第三頁寫入

在這里插入圖片描述

B. 主鍵亂序插入效果

①. 加入1#,2#頁都已經寫滿了,存放了如圖所示的數據

在這里插入圖片描述

②. 此時再插入id為50的記錄,我們來看看會發生什么現象 ?

會再次開啟一個頁,寫入新的頁中嗎?

在這里插入圖片描述

不會。因為,索引結構的葉子節點是有順序的。按照順序,應該存儲在47之后。

在這里插入圖片描述

但是47所在的1#頁,已經寫滿了,存儲不了50對應的數據了。 那么此時會開辟一個新的頁 3#。

在這里插入圖片描述

但是并不會直接將50存入3#頁,而是會將1#頁后一半的數據,移動到3#頁,然后在3#頁,插入50。

在這里插入圖片描述

移動數據,并插入id為50的數據之后,那么此時,這三個頁之間的數據順序是有問題的。 1#的下一個 頁,應該是3#, 3#的下一個頁是2#。 所以,此時,需要重新設置鏈表指針。(連接過程類似雙向鏈表的插入過程)
在這里插入圖片描述

上述的這種現象,稱之為 “頁分裂”,是比較耗費性能的操作。

3). 頁合并

目前表中已有數據的索引結構(葉子節點)如下:
在這里插入圖片描述

當我們對已有數據進行刪除時,具體的效果如下:

當刪除一行記錄時,**實際上記錄并沒有被物理刪除,只是記錄被標記(flaged)**為刪除并且它的空間 變得允許被其他記錄聲明使用。

在這里插入圖片描述

當我們繼續刪除2#的數據記錄
在這里插入圖片描述

當頁中刪除的記錄達到 MERGE_THRESHOLD(默認為頁的50%),InnoDB會開始尋找最靠近的頁(前或后)看看是否可以將兩個頁合并以優化空間使用。
在這里插入圖片描述

刪除數據,并將頁合并之后,再次插入新的數據21,則直接插入3#頁
在這里插入圖片描述

這個里面所發生的合并頁的這個現象,就稱之為 “頁合并”。

知識小貼士: MERGE_THRESHOLD(threshold:閾值):合并頁的閾值,可以自己設置,在創建表或者創建索引時指定。

4). 主鍵設計原則

  1. 滿足業務需求情況下,盡量降低主鍵長度
  2. 插入數據時盡量選擇順序插入,使用AUTO_INCREMENT主鍵
  3. 盡量不要使用UUID(無序,插入可能產生頁分裂現象,影響性能)或其他自然主鍵(如身份證號:長度比較長,檢索時會浪費大量的磁盤IO時間)
  4. 避免對主鍵進行修改(修改主鍵還需要修改對應的索引)

3. ORDER BY 優化

MySQL的排序,有兩種方式:

Using filesort : 通過表的索引或全表掃描,讀取滿足條件的數據行,然后在排序緩沖區sort buffer中完成排序操作,所有不是通過索引直接返回排序結果的排序都叫 FileSort 排序。

Using index : 通過有序索引順序掃描直接返回有序數據,這種情況即為 using index,不需要 額外排序,操作效率高。

對于以上的兩種排序方式,Using index的性能高,而Using filesort的性能低,我們在優化排序 操作時,盡量要優化為 Using index。

-- 需要優化的查詢(出現Using filesort)
explain select  id,age,phone from tb_user order by age ;
explain select  id,age,phone from tb_user order by age, phone ;
--由于 age, phone 都沒有索引,所以此時再排序時,出現Using filesort, 排序性能較低。-- 創建索引
CREATE INDEX idx_age_phone ON tb_user(age, phone);--創建索引后,根據age, phone進行升序排序
-- 優化后查詢(Using index)
explain select  id,age,phone from tb_user order by age, phone ;
--建立索引之后,再次進行排序查詢,就由原來的Using filesort, 變為了 Using index,性能就是比較高的了。
--根據age, phone進行降序一個升序,一個降序
explain select  id,age,phone from tb_user order by age desc , phone desc ;
--因為創建索引時,如果未指定順序,默認都是按照升序排序的,而查詢時,一個升序,一個降序,此時
--就會出現Using filesort。

為了解決上述的問題,我們可以創建一個索引,這個聯合索引中 age 升序排序,phone 倒序排序。

創建聯合索引(age 升序排序,phone 倒序排序)

 create  index  idx_user_age_phone_ad  on  tb_user(age asc ,phone desc);

優化后查詢(Using index)。

升序/降序聯合索引結構圖示:
在這里插入圖片描述

在這里插入圖片描述

--根據phone,age進行升序排序,phone在前,age在后。(易錯細節)
explain select  id,age,phone from tb_user order by phone , age;
--排序時,也需要滿足最左前綴法則,否則也會出現 filesort。因為在創建索引的時候, age是第一個
--字段,phone是第二個字段,所以排序時,也就該按照這個順序來,否則就會出現 Using filesort。

排序類型

  • Using index:直接通過索引返回數據(性能最佳)
  • Using filesort:需要將結果集加載到內存排序(需要優化)

order by優化原則:

A. 根據排序字段建立合適的索引,多字段排序時,也遵循最左前綴法則。(where 后的連表條件只要存在即可,無所謂順序,但order by后面的書寫有順序要求)

B. 盡量使用覆蓋索引。(減少使用select * ,不用回表)

C. 多字段排序, 一個升序一個降序,此時需要注意聯合索引在創建時的規則(ASC/DESC)。

D. 如果不可避免的出現filesort,大數據量排序時,可以適當增大排序緩沖區大小 sort_buffer_size(默認256k)。

4. GROUP BY 優化

-- 未優化(出現Using temporary)
EXPLAIN SELECT profession, COUNT(*) FROM tb_user 
GROUP BY profession;-- 創建索引后優化
CREATE INDEX idx_pro_age_sta ON tb_user(profession,age,status);
EXPLAIN SELECT profession, COUNT(*) FROM tb_user 
GROUP BY profession; -- 使用索引

優化方法

A. 在分組操作時,可以通過索引來提高效率。

B. 分組操作時,索引的使用也是滿足最左前綴法則的。

5. LIMIT 優化

在數據量比較大時,如果進行limit分頁查詢,在查詢時,越往后,分頁查詢效率越低。

我們一起來看看執行limit分頁查詢耗時對比:
在這里插入圖片描述

通過測試我們會看到,越往后,分頁查詢效率越低,這就是分頁查詢的問題所在。 因為,當在進行分頁查詢時,如果執行 limit 2000000,10 ,此時需要MySQL排序前2000010 記 錄,僅僅返回 2000000 - 2000010 的記錄,其他記錄丟棄,查詢排序的代價非常大 。

(因為葉子排序是雙鏈表,要依次遍歷,越向后時間越長。)

優化思路: 一般分頁查詢時,通過創建 覆蓋索引 能夠比較好地提高性能,可以通過覆蓋索引加子查詢形式進行優化。

explain   select  *  from  tb_sku  t  ,  (select  id  from  tb_sku  order  by  id 
limit  2000000,10)  a  where t.id  =  a.id;
-- 低效寫法(耗時隨偏移量增加)
SELECT * FROM tb_sku LIMIT 9000000,10;-- 優化方案:記錄上次查詢的最大ID
SELECT * FROM tb_sku WHERE id > 9000000 LIMIT 10;-- 子查詢優化(需覆蓋索引)
SELECT * FROM tb_sku t, 
(SELECT id FROM tb_sku ORDER BY id LIMIT 9000000,10) a 
WHERE t.id = a.id;

優化原理

  • 避免全表掃描,使用索引覆蓋
  • 使用ID分段查詢替代大偏移量

6. COUNT 優化

 select  count(*)  from  tb_user ;

我們發現,如果數據量很大,在執行count操作時,是非常耗時的。

MyISAM 引擎把一個表的總行數存在了磁盤上,因此執行 count(*) 的時候會直接返回這個數,效率很高; 但是如果是帶條件的count,MyISAM也慢。

InnoDB 引擎就麻煩了,它執行 count(*) 的時候,需要把數據一行一行地從引擎里面讀出來,然后累積計數 。

如果說要大幅度提升InnoDB表的count效率,主要的優化思路:

自己計數(可以借助于redis這樣的數 據庫進行,但是如果是帶條件的count又比較麻煩了)。

count用法

count() 是一個聚合函數,對于返回的結果集,一行行地判斷,如果 count 函數的參數不是 NULL,累計值就加 1,否則不加,最后返回累計值。

用法:count(*)、count(主鍵)、count(字段)、count(數字)
在這里插入圖片描述

--按照效率排序的話,所以盡量使用count(*),因為專門做了優化。
count(字段)(需要做判斷是否為空)< count(主鍵 id) < count(1)count(*)-- 統計有效數據條數
SELECT COUNT(1) FROM tb_user;  -- 推薦寫法
SELECT COUNT(*) FROM tb_user;  -- 官方優化寫法

不同COUNT區別

  • COUNT(字段):統計不為NULL的記錄數
  • COUNT(主鍵):遍歷主鍵索引
  • COUNT(1):不取值直接累加1
  • COUNT(*):MySQL優化過的特殊計數器

7. UPDATE 優化

回憶:InnoDB的三大特性:事務,外鍵,行級鎖

? start transaction; 或者是begin來開啟事務;

我們主要需要注意一下update語句執行時的注意事項。

update  course  set  name = 'javaEE'  where  id  =  1 ;

在這里插入圖片描述

當我們在執行更新的SQL語句時,會鎖定id為1這一行的數據,然后事務提交之后,行鎖釋放。

但是當我們在執行如下SQL時。

update course set name = 'SpringBoot' where name = 'PHP' ;

在這里插入圖片描述

name這個字段沒有索引,此時加的就不再是行鎖了,而是表鎖。一旦鎖表了,我們的并發性能就會降低!!!

當我們開啟多個事務,在執行上述的SQL時,我們發現行鎖升級為了表鎖。 導致該update語句的性能大大降低。

InnoDB的行鎖是針對索引加的鎖,不是針對記錄加的鎖 ,并且該索引不能失效,否則會從行鎖 升級為表鎖 。

-- 使用索引字段更新(行級鎖)
UPDATE tb_user SET name = 'zhangsan' WHERE id = 1;-- 無索引更新(表級鎖,需要避免!)
UPDATE tb_user SET name = 'lisi' WHERE name = 'wangwu';

優化重點

  • 更新條件必須走索引,避免行鎖升級為表鎖
  • 事務要及時提交,減少鎖持有時間

總結

優化類型核心方法典型案例
插入優化批量插入+手動事務提交+主鍵順序插入萬級數據使用LOAD DATA
主鍵優化自增主鍵+避免修改+盡量短UUID導致頁分裂問題
ORDER BY盡量建立覆蓋索引+避免filesort多字段排序注意索引順序
GROUP BY利用索引減少臨時表(多字段分組滿足最左前綴法則)分組字段建立聯合索引
LIMIT覆蓋索引+子查詢(使用ID分段替代大偏移量)百萬級分頁優化方案
COUNT優先使用COUNT(*)或COUNT(1)統計全表數據時避免COUNT(字段)
UPDATEWHERE條件必須走索引無索引更新導致表鎖問題

通過以上優化手段,通常可以使MySQL查詢性能提升1-3個數量級,特別是在大數據量場景下效果尤為顯著。實際優化中需要結合EXPLAIN執行計劃進行分析,針對性優化關鍵瓶頸點。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72448.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72448.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72448.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【AI深度學習基礎】NumPy完全指南進階篇:核心功能與工程實踐(含完整代碼)

NumPy系列文章 入門篇進階篇終極篇 一、引言 在掌握NumPy基礎操作后&#xff0c;開發者常面臨真實工程場景中的三大挑戰&#xff1a;如何優雅地處理高維數據交互&#xff1f;如何在大規模計算中實現內存與性能的平衡&#xff1f;怎樣與深度學習框架實現高效協同&#xff1f;…

Python學習第十八天之深度學習之Tensorboard

Tensorboard 1.TensorBoard詳解2.安裝3.使用4.圖像數據格式的一些理解 后續會陸續在詞博客上更新Tensorboard相關知識 1.TensorBoard詳解 TensorBoard是一個可視化的模塊&#xff0c;該模塊功能強大&#xff0c;可用于深度學習網絡模型訓練查看模型結構和訓練效果&#xff08;…

【GraphQL API 漏洞簡介】

GraphQL API 漏洞簡介 一、漏洞原理與分類二、漏洞檢測方法三、典型利用方式四、工具推薦防御建議 GraphQL API 因其靈活性和高效性被廣泛應用&#xff0c;但也因設計和實現缺陷存在多種安全風險。以下從漏洞原理、檢測方法及利用方式三個維度進行詳細分析&#xff1a; 一、漏洞…

Windows逆向工程入門之MASM數據結構使用

公開視頻 -> 鏈接點擊跳轉公開課程博客首頁 -> ???鏈接點擊跳轉博客主頁 目錄 第一章&#xff1a;MASM數據定義體系精要 1.1 基礎數據類型全景 1.1.1 整型數據規范 1.1.2 浮點數據編碼 1.2 復合數據結構 1.2.1 多維數組定義 1.2.2 復雜結構體 第二章&#xf…

筑牢安全防線:工商業場所燃氣泄漏防護新方案

燃氣安全是企業經營不可逾越的生命線。在餐飲后廚、化工車間、酒店鍋爐房等場所&#xff0c;可燃氣體一旦泄漏&#xff0c;極易引發嚴重事故。如何實現精準監測、快速響應&#xff0c;成為工業及商業領域安全管理的核心訴求。旭華智能深耕安全監測領域&#xff0c;推出的工業及…

本地部署大數據集群前置準備

1. 設置VMware網段 虛擬網絡編輯器——更改設置——選擇VMnet8——子網改成192.168.88.0——NAT設置——網關設置為192.168.88.2 2. 下載CentOS操作系統 下載CentOS 7.6(1810)版本 3. 在VMware中安裝CentOS操作系統 創建新的虛擬機——典型——安裝光盤映像文件——輸入賬…

【藍橋杯單片機】第十二屆省賽

一、真題 二、模塊構建 1.編寫初始化函數(init.c) void Cls_Peripheral(void); 關閉led led對應的鎖存器由Y4C控制關閉蜂鳴器和繼電器 由Y5C控制 2.編寫LED函數&#xff08;led.c&#xff09; void Led_Disp(unsigned char ucLed); 將ucLed取反的值賦給P0 開啟鎖存器…

PyCharm接入本地部署DeepSeek 實現AI編程!【支持windows與linux】

今天嘗試在pycharm上接入了本地部署的deepseek&#xff0c;實現了AI編程&#xff0c;體驗還是很棒的。下面詳細敘述整個安裝過程。 本次搭建的框架組合是 DeepSeek-r1:1.5b/7b Pycharm專業版或者社區版 Proxy AI&#xff08;CodeGPT&#xff09; 首先了解不同版本的deepsee…

CSS 系列之:grid 布局

基本概念 <template><div class"parent"><div class"box">p1-1</div><div class"box">p1-2</div><div class"box">p1-3</div></div><div class"parent"><…

數學軟件Matlab下載|支持Win+Mac網盤資源分享

如大家所了解的&#xff0c;Matlab與Maple、Mathematica并稱為三大數學軟件。Matlab應用廣泛&#xff0c;常被用于數據分析、無線通信、深度學習、圖像處理與計算機視覺、信號處理、量化金融與風險管理、機器人&#xff0c;控制系統等領域。 Matlab將數值分析、矩陣計算、科學…

水仙花數(華為OD)

題目描述 所謂水仙花數&#xff0c;是指一個n位的正整數&#xff0c;其各位數字的n次方和等于該數本身。 例如153是水仙花數&#xff0c;153是一個3位數&#xff0c;并且153 13 53 33。 輸入描述 第一行輸入一個整數n&#xff0c;表示一個n位的正整數。n在3到7之間&#x…

物聯網同RFID功能形態 使用場景的替代品

在物聯網&#xff08;IoT&#xff09;和自動識別技術領域&#xff0c;除了RFID標簽外&#xff0c;還有一些其他技術產品可以在形態和大小上與RFID標簽相似&#xff0c;同時提供類似或更強大的功能。以下是幾種能夠替代RFID標簽的產品&#xff1a; 一、NFC標簽 NFC&#xff08;…

03.03 QT

1.在注冊登錄的練習里面&#xff0c;追加一個QListwidget 項目列表 要求:點擊注冊之后&#xff0c;將賬號顯示到 1istwidget上面去 以及&#xff0c;在listwidget中雙擊某個賬號的時候&#xff0c;將該賬號刪除 Widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWi…

c++ cout詳解

在 C++ 中,cout 是標準輸出流對象,用于向控制臺(或標準輸出設備)輸出數據。它是 iostream 庫的核心組件之一,與 << 流插入運算符配合使用。 一、基本用法 1. 頭文件和命名空間 #include <iostream> // 必須包含的頭文件 using namespace std; // 命名空間(…

深入解析 .NET Core 的應用啟動流程

隨著 .NET Core 的發展&#xff0c;它逐漸成為構建跨平臺、高性能 Web 應用的首選框架。了解 .NET Core 的應用啟動流程是開發者成功使用該框架的關鍵&#xff0c;尤其是在調試、優化和部署時。本文將深入探討 .NET Core 的應用啟動過程&#xff0c;從創建 Web 主機、配置服務、…

(十二)基于 Vue 3 和 Mapbox GL 實現的坐標拾取器組件示例

下面是一個基于 Vue 3 和 Mapbox GL 實現的坐標拾取器組件示例: <template><div class="map-container"><div ref="mapContainer" class="map"></div><div class="coordinates-box"><div v-if=&qu…

LINUX網絡基礎 - 網絡編程套接字,UDP與TCP

目錄 前言 一. 端口號的認識 1.1 端口號的作用 二. 初識TCP協議和UDP協議 2.1 TCP協議 TCP的特點 使用場景 2.2 UDP協議 UDP的特點 使用場景 2.3 TCP與UDP的對比 2.4 思考 2.5 總結 三. 網絡字節序 3.1 網絡字節序的介紹 3.2 網絡字節序思考 四. socket接口 …

歌曲分類和流行度預測

1. 項目介紹 本項目從kaggle平臺上下載了數據集&#xff0c;該數據集包含了3萬多首來自Spotify API 的歌曲&#xff0c;共有23個特征。首先對數據集進行預處理&#xff0c;如重復行、缺失值、標準化處理等。再對預處理后的數據進行探索性分析&#xff0c;觀察各變量的分布情況&…

Trae:國內首款AI原生IDE,編程效率大提升

今年一月&#xff0c;在新聞上看到字節跳動面向海外市場推出了一款名為Trae的AI集成開發環境&#xff08;IDE&#xff09;。起初&#xff0c;我并未給予過多關注&#xff0c;因為市面上已有不少IDE集成了AI插件&#xff0c;功能也非常全面&#xff0c;而字節跳動自家的MarsCode…

實訓任務1.3 使用eNSP搭建基礎網絡

目錄 1.【實訓目標】 2.【實訓內容】 1.【實訓目標】 1.掌握eNSP仿真軟件的基本操作方法。 2.掌握使用eNSP仿真軟件搭建簡單的端到端網絡的方法。 【實訓環境】 1.硬件環境&#xff1a;每人一臺配置網卡的計算機。 2.軟件環境&#xff1a;華為eNSP仿真軟件。 2.【實訓內…