索引

索引分类:

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

主键索引

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

PRIMARY KEY(key1, key2);

唯一索引

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

UNIQUE(key);

普通索引

允许出现相同的索引内容

INDEX(key)
-- OR
KEY(key[,...])

组合索引

对表上的多个列进行索引

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 完整支持外键,并且具备事务性;

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 个区;

MySQL索引优化-LMLPHP

页是 innodb 磁盘管理的最小单位;默认 16 K,可通过 innodb_page_size 参数来修改;
B+树的一个节点的大小就是该页的值;

B+树

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

MySQL索引优化-LMLPHP

B+树层高问题

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

innodb 一个节点 16KB;

关于自增 ID

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

聚集索引

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

select * from user where id >= 18 and id < 40;

MySQL索引优化-LMLPHP

辅助索引

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

select * from user where lockyNum = 33;

MySQL索引优化-LMLPHP

innodb 体系结构

MySQL索引优化-LMLPHP

Buffer Pool

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

MySQL索引优化-LMLPHP

10-13 08:54