Mysql-innodb-B+索引

标签: mysql innodb 索引 | 发表时间:2020-05-16 15:25 | 作者:温安适
出处:https://juejin.im/welcome/backend

写在最前

这是读书笔记,Mysql,innodb系列一共3篇。

  • 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+树索引

注: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








相关 [mysql innodb 索引] 推荐:

Mysql-innodb-B+索引

- - 掘金后端
这是读书笔记,Mysql,innodb系列一共3篇. 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复制代码.

MySQL InnoDB B+树索引

- - OurMySQL
B+树索引在DB中有一个特点就是高扇出性,一般在DB中B+树的高度在2-3层左右,也就意味着只需要2-3次的IO操作即可. 而现在的磁盘每秒差不多在100次IO左右,2-3次意味着查询时间只需0.02-0.03秒. InnoDB存储引擎表是索引组织表,即表中数据安装主键顺序存放. 而聚集索引就是按照每张表的主键构造一颗B+,并且叶节点存放着整张表的行记录数据,因此也让聚集索引也是索引的一部分.

Mysql InnoDB锁

- - 数据库 - ITeye博客
抄自:http://www.cnblogs.com/qq78292959/archive/2013/01/30/2882745.html. Mysql常用存储引擎的锁机制. MyISAM和MEMORY采用表级锁(table-level locking). BDB采用页面锁(page-leve locking)或表级锁,默认为页面锁.

Mysql Innodb 引擎优化

- 彦强 - 阿辉的空间
作/译者:吴炳锡,来源:http://imysql.cn/ & http://www.mysqlsupport.cn 转载请注明作/译者和出处,并且不能用于商业用途,违者必究. InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎. InnoDB锁定在行级并且也在SELECT语句提供 一个Oracle风格一致的非锁定读.

MySQL MyISAM Engine 轉換成 InnoDB

- - 小惡魔 - 電腦技術 - 工作筆記 - AppleBOY
如果對於 InnoDB 不了解的讀者們,可以參考作者之前寫的 MySQL 預設儲存引擎: InnoDB 介紹,最近開始把原本 MySQL 5.1 預設 MyISAM Table 全部轉換成 InnoDB,MySQL 5.5 版本開始預設的儲存引擎就是 InnoDB,InnoDB 現在也非常完整,也支援 Full Text (5.6.4 開始支援).

MySQL 5.1安装InnoDB引擎

- - Gsion's Blog
安装 innodb 引擎(mysql5.1默认不安装). 可以在编译安装时,在configrue的时候,加上--with-plugins=innobase这个参数. 如果之前已经安装过,也可补装innodb引擎. 首先确定,在mysql的'plugin_dir'下有ha_innodb_plugin.so和ha_innodb.so两个文件.

[MySQL优化案例]系列 — 索引、提交频率对InnoDB表写入速度的影响

- - MySQL中文网
本次,我们来看看索引、提交频率对InnoDB表写入速度的影响,了解有哪些需要注意的. 1、关于索引对写入速度的影响: a、如果有自增列做主键,相对完全没索引的情况,写入速度约提升 3.11%; b、如果有自增列做主键,并且二级索引,相对完全没索引的情况,写入速度约降低 27.37%;. 因此,InnoDB表最好总是有一个自增列做主键.

MySQL Innodb 存储引擎参数优化

- jinbiaozhao - 服务器运维与网站架构|Linux运维|互联网研究
InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎. InnoDB锁定在行级并且也在SELECT语句提供一个Oracle风格一致的非锁定读. 这些特色增加了多用户部署和性能. 没有在InnoDB中扩大锁定的需要,因为在InnoDB中行级锁定适合非常小的空间.

MySQL MyISAM/InnoDB高并发优化经验

- jinbiaozhao - 服务器运维与网站架构|Linux运维|互联网研究
最近做的一个应用,功能要求非常简单,就是 key/value 形式的存储,简单的 INSERT/SELECT,没有任何复杂查询,唯一的问题是量非常大,如果目前投入使用,初期的单表 insert 频率约 20Hz(次/秒,我喜欢这个单位,让我想起国内交流电是 50Hz),但我估计以后会有 500Hz+ 的峰值.

MySQL 對 MyISAM、InnoDB 使用 Optimize Table

- - Tsung's Blog
系統用久了, 自然就會有不連續的碎片(fragmented)產生, 以前 Dos 使用 defrag, Windows 使用磁碟重組, 而 MySQL 則是使用 Optimize table.. 以往都是使用: 使用 PHP 對所有 MySQL Database 做 Optimize / Repair 的動作 - 這裡面的那隻程式來跑..