Mysql-innodb-B+索引

寫在最前

這是讀書筆記,Mysql,innodb系列一共3篇。mysql

  • Mysql-innodb-B+索引(本篇)
  • Mysql-innodb-鎖(預計20200523)
  • Mysql-innodb-事務預計20200530)

概述

下面是常見的建表語句:
CREATE TABLE `aid_***_detail` (
//省略全部字段
PRIMARY KEY (`id`),
KEY `range_idx` (`range_id`,`is_delete`,`range_detail_num`,`goods_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4複製代碼

其中的Key和PRIMARY就是 B+樹索引,即經常使用的索引,大機率是B+樹索引sql

注:mysql還有全文索引和hash索引。

Innodb的2種B+樹索引

彙集索引

  1. 主鍵構建B+樹,葉子節點存放一整行數據,彙集索引的葉子節點稱爲數據頁
  2. 每張表只有一個彙集索引
  3. 邏輯連續,頁經過雙向鏈表鏈接,頁中數據經過雙向鏈表維護
主鍵排序查找和範圍查找速度快。若高度爲3,須要3次IO找到數據

輔助索引

  1. 也稱非彙集索引,不影響彙集索引,一張表上能夠有多個輔助索引
  2. 葉子節點,存儲鍵值和書籤。書籤:彙集索引的鍵值
  3. 輔助索引找主鍵索引,主鍵索引找完整記錄
輔助索引B+樹高度爲3,彙集索引B+樹高度爲3,須要6次IO

Innodb建立索引的方式

彙集索引
新建表,將數據拷貝到新表,刪除老表,將新表重命名
輔助索引(FIC機制)
表上加S鎖,不用重建表,標記刪除
容許讀,阻塞寫
注:關於鎖的部分見下一篇blog:Mysql-innodb-鎖複製代碼

Cardinality 一個參數看索引好壞

索引中惟一項的估計值 ,Cardinality/n_rows_in_table 越接近1越好
n_rows_in_table 表中總記錄數。
可使用 show index from table 查看Cardinality的值。
Innodb對Cardinality的更新策略
  • 表中1/16 數據發生了變化
  • stat_modified_counter>2 000 000 000(20億)
  • ANALYZE TABLE table_name 能夠改變Cardinality,耗時慎用。
採集方式
Cardinality=(P1+P2+…+P8)*A/8
A索引中葉子節點的數量
P1..P8, Pn表示當前頁不一樣記錄的個數

聯合索引-使用技巧

(a,b,c)聯合索引的B+樹,簡圖以下:
B+對應的聚合索引
從上圖能夠看出:
例如a,b,c形式的排序了
1,2,1 在1,2,2前。
可是a,c這種形式沒有排序。
例如:2,1,4 ,2,2,3 都是 2,*,X的形式,X位沒有排序。

下面進行測試:
建立測試表:

CREATE TABLE `aid_test` (
`id` varchar(32) NOT NULL COMMENT '主鍵',
`a` varchar(32) NOT NULL,
`b` varchar(32) NOT NULL,
`c` int(11) NOT NULL,
`is_delete` int(11) NOT NULL COMMENT '0未刪除1已刪除',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '建立時間',
`update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新時間',
PRIMARY KEY (`id`),
KEY `range_idx` (`a`,`b`,`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ;複製代碼


開始測試
若聯合索引是(a,b,c)以下狀況可使用索引
select * from t where a=XX and b=xx and c=XXX
select * from t where a=XX and b=xx
select * from t where a=XX
經過執行計劃,均可以看到,都走了索引。
測試排序
explain select * from t where a =XX order by b
explain select * from t where a =XX and b=XX order by c
能夠看到,Extra項,只使用索引條件。
可是
explain select * from t where a =XX order by c
Extra項 有Using filesort!!!
若是待排序的內容不能由所使用的索引直接完成排序的話,那麼mysql有可能就要進行文件排序
Using filesort。

通過測試證實了,聚合索引的排序方式。
儘可能利用聚合索引的排序方式,優化查詢。


補充-B+數據結構

爲磁盤或其餘直接存取輔助設備設計的一種平衡查找樹

定義

1.數據存儲在葉子節點上,全部數據按照鍵值排序,各個葉子節點指針相互鏈接
2.非葉子節點存儲直到M-1個關鍵字以指示搜素的方向;關鍵字i表明子樹i+1中最小的關鍵字。
3.樹的根要麼無子節點,要麼其兒子數在2到M之間
4.除根外,全部非樹葉節點的兒子數在[M/2]和M之間
5.全部的樹葉都在相同的深度上並有[L/2]和L之間個數據項
6.M,L根據磁盤區塊大小肯定

B+數據結構操做

插入-裂項

葉子節點是否已經滿了 索引節點是否已經滿了 操做
記錄直接插入到葉子節點
拆分葉子節點
葉子節點的中間值上升到索引節點
小於中間值的,放在新的左葉
大於等於中間值的,放在右葉
拆分葉子節點
葉子節點的中間值上升到索引節點
小於中間值的,放在新的左葉
大於等於中間值的,放在右葉
拆分索引節點
索引節點的中間值上升到上層索引節點
小於中間值的,放到左邊索引節點
大於中間值的,放到右邊新索引節點

刪除合項

葉子節點小於填充因子 索引節點小於填充因子 操做
直接刪除,
若是該節點,還在索引節點中,用該節點的右節點替代
合併葉子節點,同時更新索引節點
合併葉子節點,
合併索引節點和它的兄弟節點

InnoDB的裂項

老是從中間進行分裂,會形成空間浪費。
Innodb的方式爲:
  1. 隨機插入時,從中間進行裂項
  2. 同一方向插入5條,已定位的數據後還有3個數據。從已定位後的3個記錄進行裂項
Page Header中決定的參數Page Last Insert,Page DIRECTION,Page_N_DIRECTION
相關文章
相關標籤/搜索