MySQL索引优化

索引

索引分类:

  • 主键索引
  • 唯一索引
  • 普通索引
  • 组合索引
  • 全文索引

主键索引

非空唯一索引,一个表只有一个主键索引;在 innodb 中,主键索引的 B+ 树包含表数据信息;

sql 复制代码
PRIMARY KEY(key1, key2);

唯一索引

不可以出现相同的值,可以有 NULL 值;

sql 复制代码
UNIQUE(key);

普通索引

允许出现相同的索引内容

sql 复制代码
INDEX(key)
-- OR
KEY(key[,...])

组合索引

对表上的多个列进行索引

sql 复制代码
INDEX idx(key1, key2[,...]);
UNIQUE(key1, key2[,...]);
PRIMARY KEY(key1, key2[,...]);

全文索引

将存储在数据库当中的整本书和整篇文章中的任意内容信息查找出来的技术;关键词 FULLTEXT

在短字符串中用 LIKE %;在全文索引中用 matchagainst

主键选择

innodb 中表是索引组织表,每张表有且只有一个主键;

  1. 如果显示设置 PRIMARY KEY,则该设置的 key 为代表的主键;
  2. 如果没有显示设置,则从非空唯一索引中选择;
    • 只有一个非空唯一索引,则选择该索引为主键;
    • 有多个非空唯一索引,则选择声明的第一个为主键;
  3. 没有非空唯一索引,则自动生成一个 6 字节的 _rowid 作为主键;

约束

为了实现数据完整性,对于 innodb,提供了以下几种约束:

  • primary key
  • unique key
  • foreign key
  • default
  • not null

外键约束

外键约束用来关联两个表,来保证参照完整性;MyISAM 存储引擎本身不支持外键,只起注释作用;而 innodb 完整支持外键,并且具备事务性;

sql 复制代码
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;

insert into parent values (1);
insert into parent values (2);
insert into child values (10, 1);
insert  into child values (20, 2);

delete from parent where id = 1;
  • 被引用的表为父表,引用的表为子表;
  • 外键定义时,可以设置行为 ON DELETE 和 ON UPDATE,行为发生时的操作可选择:
    • CASCADE:子表做同样行为
    • SET NULL:更新子表相应的字段为 NULL
    • NO ACTION:父类做相应行为报错
    • RESTRICT:同 NO ACTION

约束和索引的区别

创建主键索引或者唯一索引的时候同时创建了相应的约束;但是约束是逻辑上的概念;索引时一个数据结构即包含逻辑的概念也包含物理存储方式;

索引实现

索引存储

innodb 由段,区,页组成;段分为数据段,索引段,回滚段等;区大小为 1 MB(一个区有 64 个连续页构成);页的默认值为 16 K;页为逻辑页,磁盘物理页大小一般为 4 K 或 8 K;为了保证区中的页的连续,存储引擎一般一次从磁盘中申请 4-5 个区;

页是 innodb 磁盘管理的最小单位;默认 16 K,可通过 innodb_page_size 参数来修改;

B+树的一个节点的大小就是该页的值;

B+树

  • 全称:多路平衡搜索树,减少磁盘访问次数;用来组织磁盘数据,以页为单位,物理磁盘页一般为 4 K,innodb 默认页大小为 16 K;对页的访问是一次磁盘 IO,缓存中会缓存常访问的页;
  • 特征:非叶子节点只存储索引信息,叶子节点存储具体数据信息;叶子节点之间互相连接,方便范围查询;
  • 每个索引对应一个 B+ 树;

B+树层高问题

B+ 树的一个节点对应一个数据页;B+ 树层高越高要读取到内存的数据页越多,IO 次数越多;

innodb 一个节点 16KB;

假设:key 为 10byte 且指针大小 6 byte,假设一行记录的大小为 1KB;那么一个非叶子节点可存下 16KB / 16byte = 1024 个(key + point);每个叶子节点可存储 1024 行数据;

结论:2层 B+ 树叶子节点 1024 个,可容纳最大记录数为:1024*16 = 16384;3层 B+ 树叶子节点 1024*1024 ,可容纳最大记录数为:1024*1024*16 = 16777216;4层 B+ 树叶子节点 1024*1024*1024,可容纳最大记录数为:1024*1024*1024*16 = 17179869185;

关于自增 ID

  • 超过类型最大值会报错;
  • 类型 bigint 范围:( − 2 63 -2^{63} −263, 2 63 − 1 2^{63} - 1 263−1)
  • 假设采用 bigint,1 秒插入 1 亿条数据,大概需要 5849 年才会用完索引;

聚集索引

按照主键构造的 B+ 树;叶子节点中存放数据页;数据也是索引的一部分;

sql 复制代码
select * from user where id >= 18 and id < 40;

辅助索引

叶子节点不包含行记录的全部数据;辅助索引的叶子节点中,除了用来排序的 key 还包含一个 bookmark;该书签存储了聚集索引的 key;

sql 复制代码
select * from user where lockyNum = 33;

innodb 体系结构

Buffer Pool

Buffer Pool 缓存表和索引数据;采用 LRU 算法,让 Buffer Pool 只缓存比较热的数据;

相关推荐
打鱼又晒网32 分钟前
【MySQL】数据库精细化讲解:内置函数知识穿透与深度学习解析
数据库·mysql
王小小鸭37 分钟前
【开发小技巧11】用经典报表实现badge list效果,根据回显内容用颜色加以区分
oracle·oracle apex
大白要努力!37 分钟前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
tatasix1 小时前
MySQL UPDATE语句执行链路解析
数据库·mysql
南城花随雪。2 小时前
硬盘(HDD)与固态硬盘(SSD)详细解读
数据库
儿时可乖了2 小时前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
懒是一种态度2 小时前
Golang 调用 mongodb 的函数
数据库·mongodb·golang
天海华兮2 小时前
mysql 去重 补全 取出重复 变量 函数 和存储过程
数据库·mysql
gma9993 小时前
Etcd 框架
数据库·etcd
爱吃青椒不爱吃西红柿‍️3 小时前
华为ASP与CSP是什么?
服务器·前端·数据库