MySQL詳解二

MySQL詳解二

  • 索引
    • 主鍵索引
    • 唯一索引
    • 普通索引
    • 組合索引
    • 全文索引
    • 主鍵選擇
  • 約束
  • 索引實現
    • B+樹
    • 聚集索引
    • 輔助索引
    • 索引存儲
  • innodb 體系結構
  • 最左匹配原則
  • 覆蓋索引
  • 索引下推
  • 索引失效
  • 索引原則

索引

數據庫中的數據是以記錄為單位的,如果一條一條進行查找,幾十萬數據就已經到了查找的瓶頸,如果上百萬數據的話,查找就會非常的浪費時間。

索引的價值在于提高海量數據的檢索速度,只要執行了正確的創建索引的操作,查詢速度就可能提高成百上千倍。當一張表創建索引后,在數據庫底層就會為表中的數據記錄構建特定的數據結構,后續在查詢表中數據時就能通過查詢該數據結構快速定位到目標數據。

索引雖然提高了數據的查詢速度,但在一定程度上也會降低數據增刪改的效率,因為這時在對表中的數據進行增刪改操作時,除了需要進行對應的增刪改操作之外,可能還需要對底層建立的數據結構進行調整維護。

索引分類:主鍵索引、唯一索引、普通索引、組合索引、以及全文索引(elasticsearch);

主鍵索引

主鍵索引指是一個非空唯一索引,一個表只有一個主鍵索引,在 innodb 中,主鍵索引的 B+ 樹包含表數據信息。

PRIMARY KEY(key1, key2)

在這里插入圖片描述

唯一索引

UNIQUE(key)

唯一索引是某一列不會出現相同的值,但是可以是 NULL 值;
在這里插入圖片描述

普通索引

普通索引是指某一列允許出現相同的索引內容,也可以為NULL 值;

INDEX(key)
-- OR
KEY(key[,...])

在這里插入圖片描述

組合索引

組合索引所指的就是對表上的多個列進行索引。

INDEX idx(key1,key2[,...]);
UNIQUE(key1,key2[,...]);
PRIMARY KEY(key1,key2[,...]);

全文索引

將存儲在數據庫當中的整本書和整篇文章中的任意內容信息查找出來的技術,關鍵詞 FULLTEXT,在短字符串中用 LIKE % ,在全文索引中用 match 和 against 。

主鍵選擇

InnoDB 中的表是索引組織表,每張表有且僅有一個主鍵,主鍵的選擇就會存在以下幾種情況:

  • 如果顯示的設置 PRIMARY KEY ,則該設置的 KEY 為該表的主鍵;
  • 如果沒有顯示的設置,則從非空唯一索引中進行選擇,會出現以下兩種情況:
    情況一:只有一個非空唯一索引,就會選擇該索引作為主鍵索引;
    情況二:存在多個非空唯一索引,選擇聲明的第一個為主鍵;
  • 沒有非空唯一索引,則自動生成一個 6 字節的 _rowid 作為主鍵。

約束

為了實現數據的完整性,對于 innodb,提供了以下幾種約束,primary key,unique key,foreign key,default,not null。

  • primary key:非空唯一約束;
  • unique key:唯一約束;
  • foreign key:外鍵約束;
  • default:默認值約束;
  • not null:非空約束。

這兒需要特別介紹一下外鍵約束,他其實就是將幾張表給聯系起來,就像下面這樣:

create table parent (
id int not null,
primary key(id)
) engine=innodb;
create table child (
id int,
parent_id int,
foreign key(parent_id) references parent(id) ON DELETE CASCADE ON UPDATE
CASCADE
) engine=innodb;
-- 被引用的表為父表,引用的表稱為子表;
-- 外鍵定義時,可以設置行為 ON DELETE 和 ON UPDATE,行為發生時的操作可選擇:
-- CASCADE 子表做同樣的行為
-- SET NULL 更新子表相應字段為 NULL
-- NO ACTION 父類做相應行為報錯
-- RESTRICT 同 NO ACTION
INSERT INTO parent VALUES (1);
INSERT INTO parent VALUES (2);
INSERT INTO child VALUES (10, 1);
INSERT INTO child VALUES (20, 2);

child 表跟 parent 就通過外鍵約束聯系在一起,如果我們刪除 child 表中的某一行數據,那么對應的 parent 表中的某個數據也會被刪除掉,這就是外鍵約束。

約束是數據庫為我們提供的一種安全的方式,索引和約束的不同點就在于創建主鍵索引或者唯一索引的時候同時創建了相應的約束,但是約束時邏輯上的概念,索引是一個數據結構既包含邏輯的概念也包含物理的存儲方式。

索引實現

B+樹

Innodb 中的索引的數據結構是一顆 B+ 樹結構,首先我們來介紹一下 B+ 樹:

B+樹

B+ 樹是一顆多路平衡搜索樹,他的結構通過中序遍歷也是有序地,B+ 樹通常是用來減少磁盤訪問次數,組織磁盤數據,以頁為單位,物理磁盤頁一般為 4K,innodb 默認頁大小為 16K,對頁的訪問是一次磁盤 IO,緩存中會緩存常訪問的頁。

下面就是一顆 B+ 樹索引的結構,注意,每一個索引都對應著一顆 B+ 樹:
在這里插入圖片描述
B+ 樹索引結構存在一個特征,非葉子節點只存儲索引信息,葉子節點存儲具體數據信息,葉子節點之間互相連接,結點的大小是 16 KB,映射的連續的磁盤頁,方便范圍查詢。
在這里插入圖片描述
B+ 樹方便范圍查詢的點就在于我不需要每次查詢都從根節點進行遍歷,而是一次查詢就可以去搞定,從而來減少磁盤的 IO 次數的,就像下圖一樣,一次 IO 就能搞定:
在這里插入圖片描述

為什么B+ 樹映射的連續的磁盤頁?

因為映射連續的磁盤頁就是以順序 IO 的形式對磁道進行訪問,如果當次IO給出的扇區地址與上次IO結束的扇區地址是連續的,那磁頭就能很快的開始這次IO操作,這樣的多個IO操作就會加快對應的訪問效率。

因此 B+ 樹索引的優點就可以總結為以下幾點:
在這里插入圖片描述

聚集索引

按照主鍵構造的 B+ 樹,葉子節點中存放數據頁,數據也是索引的一部分。

比如說我們當前需要查找 id 大于并且小于 40 的所有學生,就會使用如下方式進行查詢:
在這里插入圖片描述

輔助索引

葉子節點不包含行記錄的全部數據,輔助索引的葉子節點中,除了用來排序的 key 還包含一個bookmark ,該書簽存儲了聚集索引的 key。

比如說我們需要查找 teacher_id = 33 的老師的所有信息,就會采用如下的查找方式:
在這里插入圖片描述
因為在輔助索引的葉子結點中存儲了一個聚集索引的書簽,當我們找到對應的節點以后,此時就需要進行一個回表查詢,又重新回到聚集索引當中,查找對應的信息,然后再進行返回數據,相對于聚集索引來說他多出來一步回表查詢的操作。

索引存儲

innodb 由段、區、頁組成;段分為數據段、索引段、回滾段等,區大小為 1 MB(一個區由 64 個連續頁構成),頁的默認值為 16k,頁為邏輯頁,磁盤物理頁大小一般為 4K 或者 8K,為了保證區中的頁連續,存儲引擎一般一次從磁盤中申請 4~5 個區。
在這里插入圖片描述

innodb 體系結構

對于 MySQL 來說,光實現以上的策略是不夠的,因為每一次訪問 B+ 樹的結點都會觸發一次 IO ,采用上面的策略了,還是會有多次磁盤 IO,所以在 MySQL 中還設計了一個 bufferpool 緩存表和索引數據;采用 LRU 算法(原理如下圖)讓 Buffer pool 只緩存比較熱的數據 。
在這里插入圖片描述
正常情況下我們刷盤操作是要經過 page cache 的,但是 page cache 屬于內核態,我們無法去定制我們自己的一個刷盤策略,所以就需要在用戶態設計一個 Buffer pool ,然后制定我們的刷盤策略,通過 Direct IO 的方式,直接將數據刷入到磁盤當中。

我們再來看一張圖示結構:在這里插入圖片描述
從上圖就可以看出,在我們的內存結構當中是存在一個 Buffer pool 的,這個 Buffer pool 就是用來緩存對應的熱點數據的,也就是說,我們對于寫數據并不是直接對磁盤空間進行操作的,而是先將其寫進用戶態的 Buffer pool 中,然后最終通過 Direct IO 的方式,將數據直接刷入到磁盤中。

我們來看一下 Buffer pool 的結構:
在這里插入圖片描述
Buffer pool 中使用的是 LRU (最近未被使用)的淘汰策略,通過上圖我們可以看出來,在 MySQL 中數據的插入的方式是選擇中間的位置進行插入的,原因就在于,我們并不認為最新被插入的數據就是熱點數據,所以并不會選擇在開頭位置進行插入,只有當我們多次對該數據進行訪問以后,他就會被挪到前面的位置,而一個數據如果長時間不被訪問到,就會被移動到后面的位置,最終通過 LRU 策略把這些數據輸入到磁盤當中。

Buffer pool 中緩存的是聚集索引也就是表和索引的數據,對于輔助索引的數據,是存在 Change buffer 中的,當我們需要讀取非唯一索引的數據時, Change buffer 當中的數據就會異步的 Merge 到 Buffer pool 當中去,同時他也會定期的同步到索引頁當中去。

在這里插入圖片描述

如下圖所示,free list 組織 buffer pool 中未使用的緩存頁;flush list 組織 buffer pool 中臟頁,也就是待刷盤的頁;lru list 組織 buffer pool 中冷熱數據,當 buffer pool 沒有空閑頁,將從 lru list 中最久未使用的數據進行淘汰。

在這里插入圖片描述

Redlog

Buffer pool 是存在于內存當中的,如果服務器突然宕機了,此時 Buffer pool 當中的數據就沒有了,我們當然不能讓這些數據都丟失,我們會將這些數據寫入到 Redlog 中去,如果出現宕機,我們就會保證 MySQL 在重啟以后將這些數據從 Redlog 中再重新讀取回來。
在這里插入圖片描述
我們可以看見,內存中是存在一個 Log Buffer 的,它采用的就是正常將數據刷入到 page cache 中,然后再將 page cache 中的數據刷入 Redlog 當中,Redlog 當中的數據也是一頁一頁連續進行存儲的,這也方便我們在讀取 Redlog 中數據的時候提高對應的效率。

整體總結下來就是 MySQL 的索引采用的 B+ 樹的結構,保證數據訪問的一個高效,然后又通過在內存中的 Buffer pool 結構,減少磁盤 IO 的操作。

最左匹配原則

對于組合索引,從左到右依次匹配,遇到 ><betweenlike 就停止匹配。

如何理解上面這句話,我們來看一張表結構:
在這里插入圖片描述
上面這張表中普通索引設置為組合索引,其中主鍵索引為 id,普通索引為name,cid,最左匹配規則就是我們在查詢的過程中首先會以 name 來進行比較,如果 name 一樣我們才會去使用 cid。

比如下面這兩句查詢語句:

這一個查詢語句 where 后面使用的是 name,此時就會踩到我們的索引結構,那么他首先會去輔助索引中進行查詢,然后回表查詢到聚集索引當中。

在這里插入圖片描述

再看這一個查詢語句,因為我們設置的最左索引為 name,此時條件為 cid了,那么就不滿足最左匹配的原則,就不會踩到對應的索引,也就意味著此時會去聚集索引中進行全表查詢,全表查詢的速度是最慢的。

在這里插入圖片描述
我們再看下面這句查詢語句,我們可以看見當前他也是踩了索引的,因為這兒會進行優化,總是執行最左匹配的條件的,name 就為我們的最左匹配規則。
在這里插入圖片描述
其中 type 表示的顯示訪問類型,采用怎么樣的方式來訪問數據,效率從好到壞依次為:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery >index_subquery > range > index > ALL

覆蓋索引

從輔助索引中就能找到數據,而不需通過聚集索引查找,利用輔助索引樹高度一般低于聚集索引樹,會進行較少磁盤 IO。

覆蓋索引并不表示索引,他表示的是一種選擇策略。

通過下面這張表就可以看出來,第二句查詢語句走的策略就是覆蓋索引,因為輔助索引 B+ 樹結構中除了包含普通索引信息之外還包含主鍵索引,我們此時需要查詢的 3 個信息均可以在輔助索引中找到,就不需要進行回表查詢。

在這里插入圖片描述

索引下推

索引下推是為了減少回表次數,提升查詢效率,在 MySQL 5.6 的版本開始推出的。

MySQL 架構分為 server 層和存儲引擎層,沒有索引下推機制之前,server 層向存儲引擎層請求數據,在 server 層根據索引條件判斷進行數據過濾;有索引下推機制之后,將部分索引條件判斷下推到存儲引擎中過濾數據,這樣就可以減少回表次數,最終由存儲引擎將數據匯總返回給 server 層。

索引失效

首先我們創建一張下面這樣的表,然后在插入一些數據:

在這里插入圖片描述

  • select ... where A and B 若 A 和 B 中有一個不包含索引,則索引失效;
    在這里插入圖片描述
  • 索引字段參與運算,則索引失效;例如: from_unixtime(idx) = '2021-04-30',需要改成 idx = unix_timestamp("2021-04-30")就不會索引失效
    在這里插入圖片描述
  • 索引字段發生隱式轉換,則索引失效;例如:將列隱式轉換為某個類型,實際等價于在索引列上作用了隱式轉換函數;
    在這里插入圖片描述
  • LIKE 模糊查詢,通配符 % 開頭,則索引失效;例如: select * from user where name like ‘%Mark’;
    在這里插入圖片描述
  • 在索引字段上使用 NOT <> != 索引失效,如果判斷 id <> 0 則修改為 idx > 0 or idx < 0 ;
  • 組合索引中,沒使用第一列索引,索引失效。

索引原則

索引原則這塊兒涉及到數據類型,可以去看一下之前的一篇文章MySQL數據類型,索引設計的原則包含以下幾個方面:

  • 查詢頻次較高且數據量大的表建立索引,索引選擇使用頻次較高,過濾效果好的列或者組合;
  • 使用短索引,這樣可以讓節點包含的信息多,進行較少磁盤 IO 操作;比如: smallint , tinyint等;
  • 對于很長的動態字符串,考慮使用前綴索引:
  • 對于組合索引,考慮最左側匹配原則、覆蓋索引;
  • 盡量選擇區分度高的列作為索引,該列的值相同的越少越好;
  • 盡量擴展索引,在現有索引的基礎上,添加復合索引,最多 6 個索引;
  • 不要 select * , 盡量只列出需要的列字段,方便使用覆蓋索引;
  • 索引列,列盡量設置為非空;
  • 可選:開啟自適應 hash 索引或者調整 change buffer。

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

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

相關文章

深度學習中的模型剪枝工具Torch-Pruning的使用

Torch-Pruning(TP)是一個結構化剪枝框架&#xff0c;源碼地址&#xff1a;https://github.com/VainF/Torch-Pruning&#xff0c;最新發布版本v1.6.0&#xff0c;License為MIT。 TP支持對各種深度神經網絡進行結構化剪枝。與通過掩碼將參數設置為零的torch.nn.utils.prune不同&a…

力扣-121.買賣股票的最佳時機

121.買賣股票的最佳時機 class Solution {public int maxProfit(int[] prices) {int min prices[0];int max 0;for (int i 1; i < prices.length; i) {max Math.max(prices[i] - min, max);if (prices[i] < min) {min prices[i];}}return max;} }小結&#xff1a;貪…

lvs原理及實戰部署

一、集群與分布式系統 1 集群 1-1概念 集群式架構是將多個相同或相似的節點組合在一起&#xff0c;形成一個邏輯上的 “整體”&#xff0c;對外提供統一的服務或資源。節點之間通常具有較高的同構性&#xff08;硬件、軟件配置相似&#xff09;&#xff0c;且緊密協作。 1-2 三…

[Linux]如何設置靜態IP位址?

自從將Ubuntu Server 24.04 LTS作業系統建置在VM上後&#xff0c;逐漸導入一些容器和微服務器並使可由其他Client端來連接使用&#xff0c;其中包含AIGC模型和自動化工作流等服務&#xff0c;例如Open-WebUI和n8n。然而&#xff0c;若VM重新開機或路由器因故斷電等等狀態&#…

【Leecode 隨筆】

文章目錄題目一&#xff1a;盛最多水的容器題目描述&#xff1a;題目分析&#xff1a;解題思路&#xff1a;示例代碼&#xff1a;深入剖析&#xff1a;題目二&#xff1a;最長無重復字符的子串題目描述&#xff1a;題目分析&#xff1a;解題思路&#xff1a;示例代碼&#xff1…

Springboot項目應用PageInfo分頁問題失效

使用github的pagehelper分頁依賴<!-- 分頁控件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.0</version><scope>compile</scope></dependency&…

【無標題】標準模型粒子行為與11維拓撲量子色動力學模型嚴格對應的全面論述

標準模型粒子行為與11維拓撲量子色動力學模型嚴格對應的全面論述標準模型粒子與拓撲結構的嚴格對應 mermaid graph LRsubgraph 標準模型粒子A[費米子] --> A1[夸克]A --> A2[輕子]B[玻色子] --> B1[規范玻色子]B --> B2[希格斯]endsubgraph 11維拓撲模型C[實體頂點…

SQL一些關于存儲過程和使用的總結

存儲過程&#xff1a;數據庫里的 "定制工具箱"存儲過程就像一個裝滿工具的箱子&#xff0c;你需要什么功能&#xff0c;就調用對應的工具。它是用 SQL 語句寫好的一段程序&#xff0c;存儲在數據庫里&#xff0c;隨時可以調用。創建存儲過程 就像在工具箱里放新工具。…

springCloud -- 微服務01

目錄 一、認識微服務 1.單體架構 2.微服務 3.SpringCloud 二、微服務拆分 1.服務拆分原則 2.服務調用 3. RestTemplate 三、服務注冊和發現 1. 注冊中心原理 2. 服務發現 2.1 服務注冊 2.2 服務發現 四、OpenFeign 一、認識微服務 1.單體架構 單體架構就是整個項目中所有功能…

Deep Multi-scale Convolutional Neural Network for Dynamic Scene Deblurring 論文閱讀

用于動態場景去模糊的深度多尺度卷積神經網絡 摘要 針對一般動態場景的非均勻盲去模糊是一個具有挑戰性的計算機視覺問題&#xff0c;因為模糊不僅來源于多個物體運動&#xff0c;還來源于相機抖動和場景深度變化。為了去除這些復雜的運動模糊&#xff0c;傳統的基于能量優化的…

PDF 拆分合并PDFSam:開源免費 多文件合并 + 按頁碼拆分 本地處理

各位打工人和學生黨們&#xff0c;你知道嗎&#xff0c;處理PDF文件簡直是咱們的日常噩夢啊&#xff0c;尤其是遇到要合并好幾個文件&#xff0c;或者從中摳幾頁出來的時候&#xff0c;簡直頭大如斗&#xff01;今天給你們安利一個神仙工具&#xff0c;PDFSam&#xff0c;聽我的…

AI產品經理面試寶典第32天:AI+工業場景落地核心問題與應答策略

一、AI+工業落地價值怎么答? 面試官:AI在工業領域能創造哪些核心價值?請用具體案例說明 你的回答: AI在工業領域創造價值的底層邏輯是"數據閉環"。以阿里云ET工業大腦為例,通過采集生產線3000+傳感器數據,構建出影響良品率的60個關鍵變量模型。當數據流經AI…

【09】MFC入門到精通——MFC 屬性頁對話框的 CPropertyPage類 和 CPropertySheet 類

文章目錄九、屬性頁對話框的類CPropertyPage類 和 CPropertySheet 類。9.1 CPropertyPage 類&#xff08;1&#xff09;構造函數&#xff08;2&#xff09;CancelToClose()函數&#xff08;3&#xff09;SetModified()函數&#xff08;4&#xff09;可重載函數9.2 CPropertyShe…

Python學習筆記4

時間:2025.7.18學習內容&#xff1a;【語法基礎】if判斷、比較運算符與邏輯運算符一、if判斷if判斷基本格式&#xff1a;if要判斷的條件&#xff0c;條件成立時要做的事情注意&#xff1a;input內默認存儲的是字符串age17 if age<18:print(未成年不能上網) scoreinput(你的成…

20250718-2-Kubernetes 應用程序生命周期管理-Pod對象:基本概念(豌豆莢)_筆記

二、Kubernetes應用程序生命周期管理&#xfeff;1. 課程內容概述主要內容&#xff1a;Pod資源共享實現機制管理命令應用自修復&#xff08;重啟策略健康檢查&#xff09;環境變量Init container靜態Pod2. Pod對象介紹&#xfeff;1&#xff09;Pod基本概念&#xfeff;&#x…

為Notepad++插上JSON格式化的翅膀

文章目錄概要安裝步驟效果展示概要 JSMinNPP.dll 是一個 Notepad 插件&#xff0c;用于壓縮 JavaScript 代碼和格式化JSON字符床。以下是安裝和使用的詳細步驟&#xff1a; 安裝步驟 下載 JSMinNPP.dll 插件 https://pan.quark.cn/s/73dd0ac225be 放置 DLL 文件 打開 Notepa…

STM32-第七節-TIM定時器-3(輸入捕獲)

一、簡介&#xff1a;1.名稱&#xff1a;IC&#xff0c;輸入捕獲2.電路&#xff1a;如圖為通用定時器框圖&#xff0c;下半部分的左半模塊&#xff0c;與輸出比較部分共用捕獲/比較寄存器與引腳。3.功能&#xff1a;當通道輸入引腳出現電平跳變時&#xff0c;當前CNT的值&#…

Console 納管 Elasticsearch 9(二):日志監控

前面介紹過 INFINI Console 納管 Elasticsearch 9&#xff08;一&#xff09;&#xff0c;進行指標監控、數據管理、DSL 語句執行&#xff0c;但日志監控功能需要結合 Agent 才能使用。現在來實現一下&#xff1a; Agent 需要和 ES 部署到同一機器上&#xff0c;這里是在我本地…

實訓十——路由器與TCP/IP模型

補充拓撲圖&#xff08;交換機串聯通信&#xff09;電腦A——交換機S1——交換機S2——電腦B問&#xff1a;A和B如何通信&#xff1f;首先A會將通信的數據封裝好&#xff0c;將源端口、目標端口&#xff0c;源地址、目標地址&#xff0c;源MAC、目標MAC封裝起來&#xff0c;但是…

【Android】ViewBinding(視圖綁定)

一、什么是ViewBindingViewBinding是Android Studio 3.6推出的新特性&#xff0c;旨在替代findViewById(內部實現還是使用findViewById)。通過ViewBinding&#xff0c;可以更輕松地編寫可與視圖交互的代碼。在模塊中啟用ViewBinding之后&#xff0c;系統會為該模塊中的每個 XML…