各個數據頁可以組成一個`雙向鏈表`,而每個數據頁中的記錄會按照主鍵值從小到大的順序組成一個`單向鏈表`,每個數據頁都會為存儲在它里邊兒的記錄生成一個`頁目錄`,在通過主鍵查找某條記錄的時候可以在`頁目錄`中使用二分法快速定位到對應的槽,然后再遍歷該槽對應分組中的記錄即可快速找到指定的記錄

`目錄項記錄`和普通的`用戶記錄`的不同點:
* `目錄項記錄`的`record_type`值是1,而普通用戶記錄的`record_type`值是0。
* `目錄項記錄`只有主鍵值和頁的編號兩個列,而普通的用戶記錄的列是用戶自己定義的,可能包含很多列,另外還有`InnoDB`自己添加的隱藏列。
* `min_rec_mask`,只有在存儲`目錄項記錄`的頁中的主鍵值最小的`目錄項記錄`的`min_rec_mask`值為`1`,其他別的記錄的`min_rec_mask`值都是`0`。
#### 聚簇索引
1. 使用記錄主鍵值的大小進行記錄和頁的排序,這包括三個方面的含義:
* 頁內的記錄是按照主鍵的大小順序排成一個單向鏈表。
* 各個存放用戶記錄的頁也是根據頁中用戶記錄的主鍵大小順序排成一個雙向鏈表。
* 存放目錄項記錄的頁分為不同的層次,在同一層次中的頁也是根據頁中目錄項記錄的主鍵大小順序排成一個雙向鏈表。
2. `B+`樹的葉子節點存儲的是完整的用戶記錄。
所謂完整的用戶記錄,就是指這個記錄中存儲了所有列的值(包括隱藏列)。
我們把具有這兩種特性的`B+`樹稱為`聚簇索引`,所有完整的用戶記錄都存放在這個`聚簇索引`的葉子節點處。這種`聚簇索引`并不需要我們在`MySQL`語句中顯式的使用`INDEX`語句去創建(后邊會介紹索引相關的語句),`InnoDB`存儲引擎會自動的為我們創建聚簇索引。另外有趣的一點是,在`InnoDB`存儲引擎中,`聚簇索引`就是數據的存儲方式(所有的用戶記錄都存儲在了`葉子節點`),也就是所謂的索引即數據,數據即索引。
**將數據和索引放到一起存儲**,索引結構的葉子節點保留了數據行。每個表一定會有一個聚集索引,整個表的數據存儲以b+樹的方式存在文件中,**b+樹葉子節點中的key為主鍵值,data為完整記錄的信息;非葉子節點存儲主鍵的值。**
#### 二級索引(非聚簇索引)
和聚簇索引區別
* 使用記錄`c2`列的大小進行記錄和頁的排序,這包括三個方面的含義:
* 頁內的記錄是按照`索引`列的大小順序排成一個單向鏈表。
* 各個存放用戶記錄的頁也是根據頁中記錄的`索引`列大小順序排成一個雙向鏈表。
* 存放目錄項記錄的頁分為不同的層次,在同一層次中的頁也是根據頁中目錄項記錄的`索引`列大小順序排成一個雙向鏈表。
* `B+`樹的葉子節點存儲的并不是完整的用戶記錄,而只是`索引列+主鍵`這兩個列的值。
* 目錄項記錄中不再是`主鍵+頁號`的搭配,而變成了`索引列+頁號`的搭配。
如果返回的列不在非聚簇索引樹種, 則還需要根據得到的主鍵去聚簇索引里查詢詳細信息, 此過程叫**回表**
**覆蓋索引**:索引字段覆蓋了查詢語句涉及的字段,直接通過索引文件就可以返回查詢所需的數據,不必通過回表操作。
## 索引
* 每個索引都對應一棵`B+`樹,`B+`樹分為好多層,最下邊一層是葉子節點,其余的是內節點。所有`用戶記錄`都存儲在`B+`樹的葉子節點,所有`目錄項記錄`都存儲在內節點。
* `InnoDB`存儲引擎會自動為主鍵(如果沒有它會自動幫我們添加)建立`聚簇索引`,聚簇索引的葉子節點包含完整的用戶記錄。
* 我們可以為自己感興趣的列建立`二級索引`,`二級索引`的葉子節點包含的用戶記錄由`索引列 + 主鍵`組成,所以如果想通過`二級索引`來查找完整的用戶記錄的話,需要通過`回表`操作,也就是在通過`二級索引`找到主鍵值之后再到`聚簇索引`中查找完整的用戶記錄。
* `B+`樹中每層節點都是按照索引列值從小到大的順序排序而組成了雙向鏈表,而且每個頁內的記錄(不論是用戶記錄還是目錄項記錄)都是按照索引列的值從小到大的順序而形成了一個單鏈表。如果是`聯合索引`的話,則頁面和記錄先按照`聯合索引`前邊的列排序,如果該列值相同,再按照`聯合索引`后邊的列排序。
* 通過索引查找記錄是從`B+`樹的根節點開始,一層一層向下搜索。由于每個頁面都按照索引列的值建立了`Page Directory`(頁目錄),所以在這些頁面中的查找非常快。
## 索引的代價
* 空間
每建立一個索引都要為它建立一棵`B+`樹,每一棵`B+`樹的每一個節點都是一個數據頁,一個頁默認會占用`16KB`的存儲空間,一棵很大的`B+`樹由許多數據頁組成
* 時間
每次對表中的數據進行增、刪、改操作時,都需要去修改各個`B+`樹索引。而增、刪、改操作可能會對節點和記錄的排序造成破壞,所以存儲引擎需要額外的時間進行一些記錄移位,頁面分裂、頁面回收啥的操作來維護好節點和記錄的排序。
`WHERE`子句中的幾個搜索條件的順序對查詢結果沒有影響, MySQL的優化器是很智能的.
1. `B+`樹索引在空間和時間上都有代價,所以沒事兒別瞎建索引。
2. `B+`樹索引適用于下邊這些情況:
* 全值匹配
* 匹配左邊的列
* 匹配范圍值
* 精確匹配某一列并范圍匹配另外一列
* 用于排序
* 用于分組
3. 在使用索引時需要注意下邊這些事項:
* 只為用于搜索、排序或分組的列創建索引
* 為列的基數大的列創建索引
* 索引列的類型盡量小
* 可以只對字符串值的前綴建立索引
* 只有索引列在比較表達式中單獨出現才可以適用索引
* 為了盡可能少的讓`聚簇索引`發生頁面分裂和記錄移位的情況,建議讓主鍵擁有`AUTO_INCREMENT`屬性。
* 定位并刪除表中的重復和冗余索引
* 盡量使用`覆蓋索引`進行查詢,避免`回表`帶來的性能損耗。
- 學習地址
- MySQL
- 查詢優化
- SQL優化
- 關于or、in、not in、!=等走不走索引的說明
- 千萬級數據查詢優化
- MySQL 深度分頁問題
- 嵌套循環 Block Nested Loop 導致索引查詢慢
- MySQL增加日志統計表優化各種日志表的統計功能
- MySQL單機讀寫QPS(性能)優化
- sqlMode 置 select 的值可以比 group 里的多
- drop、delete、truncate的區別
- 尚硅谷MySQL數據庫高級學習筆記
- MySQL架構
- 事務部分
- MySQL知識點
- mysql索引
- Linux docker安裝 mysql 8.0.25
- docker 安裝mysql 5.7
- mysql Field ‘xxx’ doesn’t have a default value
- mysql多實例
- docker中的sql文件導入
- mysql進階知識
- mysql字符集
- 連接的原理
- redo日志
- InnoDB存儲引擎
- InnoDB的數據存儲結構
- B+樹索引
- 文件系統-表空間
- Buffer Pool
- 億級數據導入到es
- MySQL數據復制
- MySQL缺少主鍵的表數據
- mysql update 其中更新的字段根據另一個更新字段作為條件去更新
- MySQL指定字段值排序(將指定值排在前面)
- 設置MySQL連接數、時區
- Navicat15右鍵刪除數據刷新就又恢復了
- MySQL替換字段部分內容
- Java和MySQL統計本周本月本季和年
- 分頁時order by 排序數據重復,丟失
- mysql同一張表根據某個字段刪除重復數據
- mysqldump定時全量熱備
- 專題總結
- 事務
- MySQL事務
- spring事務
- spring事務本類調用
- spring事務傳播行為
- spring事務失效問題
- 鎖和Transactional注解一塊使用的問題
- 數據安全
- 敏感數據
- SQL注入
- 數據源
- XSS
- 接口設計
- 緩存設計
- 限流
- 自定義注解實現根據用戶做QPS限流
- 架構
- 高可用
- Java
- Unsatisfied dependency expressed through field ‘baseMapper‘
- mybatisplus多數據源
- 單個字母前綴的java變量
- spring
- spring循環依賴解決
- 事務@Transactional
- yml 文件配置信息綁定到java工具類的靜態變量上
- @Configuration @Component 區別
- springboot啟動yml文件報錯
- spring方法重試注解Retryable
- spring讀取yml集合數據
- spring自定義注解
- 獲取resource下的圖片資源
- 手機號和電話號的正則驗證
- 獲取字符串中的數字
- mybatis
- mybatis多參數添加數據并返回主鍵
- 統一異常處理
- 分組校驗
- Java讀取Python json.dumps 函數保存的redis數據
- springboot整合springCache
- 若依mybatis值為null的字段沒有返回
- 若依
- 接口白名單
- @JsonFormat時區問題
- RequestParam.value() was empty on parameter 0
- jdk8和hutool請求第三方的https報錯
- springMVC
- springMVC與vue使用post傳數組
- elementUI 時間組件報錯問題
- vue具名插槽slot
- springboot配置maven的profiles(配置微服務多環境切換打包)
- resources 配置文件讀取順序
- Windows的cmd部署jar注意事項
- Java基礎
- JUC(鎖-并發-線程池)
- CAS
- Java 鎖簡介
- synchronized和Logk有什么區別?用新的ock有什么好處
- synchronized鎖介紹
- CompletableFuture
- 多線程
- 線程池
- 集合類
- map見過的小問題
- 退出雙層循環
- StringBuilder和StringBuffer核心區別
- 日志打印
- 打印log日志
- log日志文件生成配置
- 日期時間
- 時間戳轉為時間
- 并發工具
- 連接池
- http調用
- 內網訪問天地圖
- 判等問題
- 數值計算
- null問題
- 異常處理
- 文件IO
- 序列化
- 內存溢出OOM
- Double轉String出現E的問題
- springboot接收前端表單提交多字段和上傳文件
- 子線程的錯誤, 全局異常處理捕獲不到
- vue同一個項目訪問多個不同ip地址接口
- Autowired注解導入為null
- shiro
- UnavailableSecurityManagerException錯誤
- Windows服務器80端口被占用
- java圖片增加水印
- springcloud
- Feign方法配置錯誤導致jar包啟動失敗
- feign調用超時
- Springcloud從Nacos的yml文件讀取出錯
- 定時任務quartz
- JavaPOI導出Excel
- 合并行和列
- 設置樣式
- 設置背景色
- docker
- Linux 安裝
- docker命令
- docker網絡
- docker數據卷
- dockerfile
- docker安裝ping命令
- docker-compose
- docker-compose文件內容介紹
- Linux關閉docker開機啟動
- jar打包為鏡像
- 遷移docker容器存儲位置
- Nginx
- Linux在線安裝Nginx
- nginx.conf 核心配置文件
- vue 和 nginx 刷新頁面會報404
- nginx 轉發給三個集群的tomcat
- ServerName匹配規則
- Nginx負載均衡策略
- location 匹配規則
- Nginx 搭建前端調用后臺接口的集群
- alias與root
- nginx 攔截 post 請求, 帶參數轉發到前端頁面
- 防盜鏈配置
- Nginx的緩存
- 通用Nginx配置
- nginx配置文件服務器
- 后臺jar包得不到正確ip,nginx代理時要處理
- 升級使用websocket協議
- 設置IP黑/白名單
- vue項目get請求Nginx返回html頁面post返回405錯誤
- Nginx限制所有接口流量
- Redis
- 緩存數據一致性
- 內存淘汰策略
- Redis數據類型
- gmt6
- Linux安裝GMT6
- GMT6配置中文
- GMT文件修改Windows版本到Linux版本
- 注意GMT不同字體導致符號不同的問題
- GMT繪制南海諸島小圖
- GMT生成中文圖例
- elasticsearch
- 安裝配置
- Linux安裝配置elasticsearch7.6.2
- Linux 安裝 kibana 7.6.2
- 安裝7.6.2中文分詞器
- docker 安裝elasticsearch7.6.2
- 安裝Logback7.6.2
- springboot使用
- 0. elasticsearch賬號密碼模式訪問
- 1. 配置連接
- 2. 索引
- 3. 批量保存更新
- Result window is too large 10000
- elasticsearch 分詞的字段做排序 fielddata, 設置fielddata=true 無效果
- elasticsearch 完全匹配查詢(精確查詢)
- 模糊搜索
- 日期區間查詢
- 6.x基礎知識
- 自定義詞庫
- elasticsearch集群
- 搜索推薦Suggester
- 查詢es保存的數組
- 億級mysql數據導入到es
- es 報錯 ORBIDDEN/12/index read-only
- es核心概念
- es的分布式架構原理
- 優化大數據量時的ES查詢性能
- canal
- 1. mysql的Binlog
- 2. Canal 的工作原理
- 3. canal同步es
- JVM
- 1 類的字節碼
- 2. 類的加載
- JVM知識點
- Maven
- 依賴沖突
- xxl-job
- docker 安裝配置 xxl-job
- idea
- springboot啟動報錯命令過長
- services統一啟動微服務各模塊
- 云服務器安裝寶塔面板
- 突然出現啟動或者運行特別慢
- 有導入依賴但是顯示紅色同時點擊進去也有依賴
- Linux
- sh文件執行報錯: command not found
- 使用vagrant安裝虛擬機
- Linux 開啟端口
- 開放端口
- 復制文件夾及其文件到另一個文件夾
- 兩個服務器之間映射端口
- TCP協議
- 分層模型
- TCP概述
- 支撐 TCP 協議的基石 —— 首部字段
- 數據包大小對網絡的影響 —— MTU 與 MSS 的奧秘
- 端口號
- 三次握手
- TCP 自連接
- 四次揮手
- TCP 頭部時間戳
- 分布式
- 分布式腦裂問題
- 分布式事務
- 基礎知識
- 實現分布式事務的方案
- 阿里分布式事務中間件seata
- 冪等性問題
- 其他工具
- webstorm git提交代碼后project目錄樹不顯示
- 消息隊列
- 如何保證消費的順序
- 數據結構
- 漫畫算法:小灰的算法之旅
- oracle