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 只缓存比较热的数据;

相关推荐
岁岁岁平安几秒前
mysql上课总结(2)(DCL的所有操作总结、命令行快速启动/关闭mysql服务)
数据库·mysql·命令行·权限·dcl·localhost
Boboboobo几秒前
记MySQL下一次DEPENDENT SUBQUERY的优化
数据库·sql·mysql·性能优化
hummhumm10 分钟前
Oracle 第13章:事务处理
开发语言·数据库·后端·python·sql·oracle·database
隐居的遮天恶鬼1 小时前
Mac OS 搭建MySQL开发环境
数据库·mysql·mac
abandondyy3 小时前
MySQL---主从复制和读写分离
数据库·mysql
DEARM LINER4 小时前
mysql 巧妙的索引
数据库·spring boot·后端·mysql
不惑_5 小时前
Redis与MySQL双写一致性的缓存模式
redis·mysql·缓存
码农幻想梦5 小时前
实验九 视图的使用
前端·数据库·oracle
影子落人间5 小时前
Oracle创建存储过程,创建定时任务
数据库·oracle
大G哥5 小时前
02、Oracle过滤和排序数据
数据库·oracle