MySQL學習筆記-索引

来源:https://www.cnblogs.com/yellowsea/archive/2023/04/14/17318981.html
-Advertisement-
Play Games

索引 索引(index)是幫助MySQL高效獲取數據的==數據結構(有序)==。在數據之外,資料庫系統還維護著滿足特定查找演算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找演算法,這種數據結構就是索引。 無索引的查找:全表掃描(將整張表遍歷一遍),性能極低。 ...


索引

索引(index)是幫助MySQL高效獲取數據的數據結構(有序)。在數據之外,資料庫系統還維護著滿足特定查找演算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找演算法,這種數據結構就是索引。

  • 無索引的查找:全表掃描(將整張表遍歷一遍),性能極低。

  • 有索引的查找:資料庫系統在存儲數據的同時會維護一種數據結構(如二叉樹),當需要查找時,利用該數據結構進行查找,性能較高。

  • 索引的優缺點

image-20230403104353418

一. 索引結構

MySQL的索引是在存儲引擎層實現的,不同的存儲引擎有不同的結構。

image-20230403104609783

  • 索引在存儲引擎中的支持情況

image-20230403104744836

  • 平常所說的索引,如果沒有特別指明,一般都是說B+樹結構組織的索引

1. B+樹

1.1 二叉樹

image-20230403111008578

  • 一種經典的數據結構。

  • 二叉樹的兩個缺點:

    • 順序存儲二叉樹時,會形成一條鏈表,二叉樹的深度很大,效率很低。
    • 二叉樹的度不大於2,在資料庫中存有大量數據的時候深度很大,效率很低。

1.2 紅黑樹

image-20230403111342398

  • 一種自平衡的特殊二叉樹。

  • 可以解決二叉樹可能形成鏈表的缺點,但是依舊存在數據量大時深度很大的問題。

1.3 B樹(平衡多路查找樹)

image-20230403111959716

  • 一種自平衡的樹。可以解決二叉樹的兩個缺點。
  • 一個節點可以擁有兩個以上的子節點。

1.4 B+樹

image-20230403112217055

  • B樹的變種。
  • B+樹與B樹的區別:
    • 所有的元素都會出現在葉子節點。
    • 葉子節點形成了一條單向鏈表。

1.5 MySQL中的B+樹

image-20230403112420607

  • 在MySQL中,對B+樹進行了優化。在原有基礎上,葉子節點改為了雙向迴圈鏈表,提高區間訪問的性能。

2. Hash

哈希索引就是採用一定的Hash演算法,將鍵值換算成新的Hash值,映射到對應的槽位上,然後存儲在Hash表中。

如果兩個(或多個)鍵值映射到同一個槽位上,產生了Hash衝突,可以通過鏈表解決。

image-20230403112944770

2.1 Hash索引的特點

  1. 只能用於對等比較(=,in),不支持範圍查詢(between,>,<,...)。
  2. 無法利用索引完成排序操作。
  3. 查詢效率高,通常只需要一次檢索(不出現hash衝突),效率高於B+樹。

2.2 存儲引擎支持

在MySQL中,支持hash索引的是Memory引擎,而InnoDB中具有自適應hash功能,hash索引是存儲引擎根據B+樹索引在指定條件下自動構建的。

二. 索引分類

image-20230403113658879

  • 在InnoDB存儲引擎中,根據索引的存儲形式,又可以分為以下兩種:

image-20230403113904289

  • 聚集索引的選取規則:
    • 如果存在主鍵,主鍵索引就是聚集索引。
    • 如果不存在主鍵,將適用第一個唯一(UNIQUE)索引作為聚集索引。
    • 如果不存在主鍵,或沒有合適的唯一索引,則InnoDB會自動生成一個rowid作為隱藏的聚集索引。
  • 聚集索引和二級索引的示意圖:

image-20230403114330417

  • 在查找時,先走二級索引,找到對應的主鍵後,再走聚集索引,找到對應的整個行。(回表查詢)

三. 索引語法

1. 創建索引

create [unique|fulltext] index {索引名} on {表名} ({欄位名},...);
  • unique 唯一索引 |fulltext 全文索引 |不加這兩個則說明是常規索引。
  • 一個索引可以關聯多個欄位,如果一個索引只關聯一個欄位,叫單列索引,如果關聯多個欄位,叫聯合索引(組合索引)
  • 聯合索引的欄位順序是有講究的。
  • 索引名一般的命名規則:idx _ 表名 _ 欄位名

2. 查看索引

show index form {表名};

3. 刪除索引

drop index {索引名} on {表名};

四. SQL性能分析

做性能分析是為了做SQL優化,SQL主要是做查詢優化,因為查詢操作比增刪改多,查詢優化的關鍵在於索引。

1. SQL執行頻率

# 查看當前資料庫的增刪改查的訪問頻次
show global status like 'Com_______';
# 模糊匹配'Com'後面是7個下劃線

image-20230411153543375

  • 根據執行頻率來判斷SQL優化需要在哪方面進行,也就是說這個資料庫哪個操作頻率高就優化哪個操作。

2. 慢查詢日誌

慢查詢日誌記錄了所有執行時間超過制定參數 (long_query_time,單位:秒,預設10秒) 的所有sql語句的日誌

慢查詢日誌用於找到執行慢的sql語句,進行針對性優化。

2.1 開啟慢查詢日誌

MySQL的慢查詢日誌預設沒有開啟,需要在MySQL的配置文件(/etc/my.cnf) 中配置。

  • 查詢是否開啟
show variables like 'slow_query_log';
  • 開啟慢查詢日誌

在MySQL的配置文件(/etc/my.cnf) 中配置如下信息:

# 開啟MySQL慢查詢日誌開關
show_query_log = 1
# 設置慢查詢日誌的時間為2秒,SQL語句執行時間超過2秒就會被記錄
long_query_time = 2

配置完畢後,需要重啟伺服器。

# 重啟伺服器
systemctl restart mysqld

2.2 查看慢查詢日誌

# 慢查詢日誌存放地址 Linux下
/var/lib/mysql/localhost-slow.log

image-20230411155034464

3. profile詳情

Show profiles 能夠在做SQL優化時幫助我們瞭解時間都耗費到哪裡去了。

3.1 查看MySQL是否支持profile操作

select @@have_profiling;

3.2 打開profile開關

# 查看是否打開
select @@profiling;

# 打開profile開關
set [session|global] profiling = 1;
  • profile預設是關閉的。

  • [session|global] 可以指定是會話級別的還是全局的。

3.3 查看profile詳情

# 查看每一條SQL的耗時基本情況
show profiles;

# 查看指定query_id的SQL語句各個階段的耗時情況
show profile for query query_id;

# 查看指定query_id的SQL語句CPU的使用情況
show profile cup for query query_id;
  • query_id指的是在profiles中的某一條指令的id,可以在show profiles中看到。

4. explain執行計劃

explain 或者 desc命令獲取MySQL如何執行select語句的信息,包括在select語句執行過程中表如何連接和連接的順序。

# 直接在select語句之前加上關鍵字explain/desc
explain select {欄位列表} from {表名} where {條件};
  • explain執行計劃各欄位含義

image-20230411163705430

image-20230411163917602

五. 索引使用

1. 最左首碼法則

  • 如果索引了多列(聯合索引),要遵循最左首碼法則。最左首碼法則是指查詢從索引的最左列開始,並且不跳過索引中的列。

  • 如果跳躍某一列,索引將部分失效(後面的欄位索引失效)

  • 查詢時左邊欄位存在即符合最左首碼法則,不管它在代碼中的位置。

2. 範圍查詢

  • 聯合索引中,出現範圍查詢(> , <),範圍查詢右側的列索引失效
  • 用(>= , <=)不會出現失效情況。

3. 索引列運算

  • 不要在索引列上進行運算操作,否則索引將失效

4. 字元串不加引號

  • 字元串類型欄位使用時,不加引號,索引將失效

5. 模糊查詢

  • 如果是尾部進行模糊查詢,索引不會失效;如果是頭部進行模糊查詢,索引會失效

6. or連接的條件

  • 用or分割開的條件,如果or前的條件中的列有索引,二後面的列沒有索引,那麼涉及的索引都不會被用到
  • 只要把沒有索引的建立一個索引就可以解決失效問題。

7. 數據分佈影響

  • 如果MySQL評估使用索引比全表更慢,則不使用索引

8. SQL提示

SQL提示是優化資料庫的一個重要手段。在SQL語句中加入一些人為的提示來達到優化操作的目的。

8.1 use index

  • 使用指定索引(建議)
select * from {表名} use index({索引名}) where...;

8.2 ignore index

  • 不使用某個索引
select * from {表名} ignore index({索引名}) where...;

8.3 force index

  • 使用指定索引(必須)
select * from {表名} force index({索引名}) where...;

9. 覆蓋索引

  • 儘量使用覆蓋索引(查詢使用了索引,並且需要返回的列,在該索引中已經全部能夠找到),減少使用select *。

  • 使用覆蓋索引和沒有使用覆蓋索引,在explain中的Extra列有不一樣的提示:

    • (沒使用)using index condition : 查找使用了索引,但是需要回表查詢數據。
    • (使用了)using where; using index : 查找使用了索引,但是需要的數據都在索引列中能夠找到,所以不需要回表查詢數據。
  • 覆蓋索引直接在二級索引中獲取了返回所需的所有數據,所以不需要回表查詢,查詢速度快。

  • 如果不是覆蓋查詢,在二級索引中查詢到數據後,還需要拿到對應數據的主鍵,到聚焦索引中查詢行數據,這就叫回表查詢,所以速度慢。

10. 首碼索引

當欄位類型為字元串時,有時候需要存儲很長的字元串,如果建立索引,索引會變得很大,浪費大量磁碟IO,影響查詢效率。

此時可以只用字元串的一部分首碼來建立索引(首碼索引),可以大大節約索引空間,從而提高效率。

10.1 創建首碼索引

create index {索引名} on {表名}({欄位名}({首碼的字元數}));

10.2 首碼長度的選擇

  • 可以根據索引的選擇性來決定。

  • 選擇性:不重覆的索引值和數據表的記錄總數的比值。索引選擇性越高,效率越高。唯一索引的選擇性是1,是性能最好的。

  • 求選擇性:

select count(distinct substring({欄位名},1,{截取長度}))/count(*) from {表名};

11. 單列索引和聯合索引

  • 單列索引:一個索引只包含單個列

  • 聯合索引:一個索引包含了多個列

  • 在業務場景中,如果存在多個查詢條件,考慮針對查詢欄位建立索引時,建議使用聯合索引。

  • 聯合索引的存儲結構:

image-20230414171408279

六. 索引設計原則

image-20230414171642246


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

-Advertisement-
Play Games
更多相關文章
  • C#多線程學習(一) 多線程的相關概念 什麼是進程? 當一個程式開始運行時,它就是一個進程,進程包括運行中的程式和程式所使用到的記憶體和系統資源。 而一個進程又是由多個線程所組成的。 什麼是線程? 線程是程式中的一個執行流,每個線程都有自己的專有寄存器(棧指針、程式計數器等), 但代碼區是共用的,即不 ...
  • SqlSugar的開發框架本身主要是基於常規關係型資料庫設計的框架,支持多種資料庫類型的接入,如SqlServer、MySQL、Oracle、PostgreSQL、SQLite等資料庫,非關係型資料庫的MongoDB資料庫也可以作為擴展整合到開發框架裡面,通過基類的繼承關係很好的封裝了相關的基礎操作... ...
  • 日常開發過程中,驗證字元的合法性一直是一個必不可少的步驟,以前都是在用戶輸入完再做判斷,不僅麻煩在不符合標準的時候還要提示用戶修改,體驗很差,為什麼不在輸入的時候加以限制呢? ...
  • 因為Grpc採用HTTP/2作為通信協議,預設採用LTS/SSL加密方式傳輸,比如使用.net core啟動一個服務端(被調用方)時: public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultB ...
  • NuGet 引入依賴庫 PM> Install-Package Tron.Wallet.Net 隨機生成私鑰和對應的地址 using Tron.Wallet.Net; namespace ConsoleApp1 { internal class Program { static async Task ...
  • 簡介:本文主要介紹ubuntu20.04容器中搭建xfce遠程桌面、C++、Go環境、容器內docker操作配置、zsh配置 一、創建容器 1、創建容器 docker pull ubuntu:20.04docker run -itd --privileged --name=my-desktop--u ...
  • 1、下載redis源碼包,併進行解壓縮操作 https://download.redis.io/releases/ [root@Redis-Ubuntu-1804-p21:~]# wget https://download.redis.io/releases/redis-5.0.14.tar.gz ...
  • 掃碼獲取搭建步驟: 實驗名稱: Samba共用伺服器基本配置 簡答題(直接打字回答在題目下方,僅完成4道題目的同學,最高30分。另外70分是加給自己搭建實驗環境完成實驗報告的同學): 1、Samba是什麼,有什麼用處? 2、CentOS系統中,線上安裝Samba服務,用什麼命令? 3、CentOS系 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...