索引的创建和设计原则

  • 1. 索引的分类
  • 1.1 普通索引
  • 1.2 唯一性索引
  • 1.3 主键索引
  • 1.4 单列索引
  • 1.5 多列(联合,组合)索引
  • 1.6 全文索引
  • 2. 索引的创建
  • 2.1 创建表时创建索引
  • 1. 隐式创建
  • 2. 显式创建
  • 3. 全文检索
  • 2.2 创建表后创建索引
  • 1. alter table 的方式
  • 2. create index 的方式
  • 3. 索引的删除
  • 4. 索引新特性
  • 4.1 支持降序索引
  • 4.2 隐藏索引
  • 1. 创建隐藏索引的方式
  • 2. 修改索引是否隐藏


1. 索引的分类

按照功能逻辑进行分类:普通索引,唯一性索引,主键索引,全文索引

按照物理方式进行分类:聚簇索引,非聚簇索引

按照作用字段个数分类:单列索引,联合索引

1.1 普通索引

在创建索引时,不加任何的限制条件。这类索引可以创建在任何数据类型,其值是否为空和唯一,是由字段本本身的约束条件所决定

1.2 唯一性索引

使用 UNIQUE参数 可以设置唯一性索引,在创建唯一性索引时,限制该索引值必须是唯一的,但允许有空值

1.3 主键索引

主键索引就是一种特殊的唯一性索引,在唯一索引的基础上增加了不为空的约束,也就是 NOT NULL+UNIQUE,一张表里面最多只有一个主键索引。

why?

这是由主键索引的物理实现方式决定的,因为数据在内存中只能按照一种顺序进行存储

1.4 单列索引

作用在一个字段上的索引就是单列索引

1.5 多列(联合,组合)索引

作用在多个字段上的索引,使用时遵循最左前缀原则。

1.6 全文索引

全文索引是目前搜索引擎使用的一种关键技术,适用于大规模数据的检索。使用 FULLTEXT 可以设置全文索引。在整个索引中出现的次数越少的词语,匹配时的相关度就越高。

在当前的大数据时代,关系型数据库对全文索引的需求力不从心。逐渐被其他的搜索引擎代替,所以在MySQL当中,并不会去使用全文索引。

2. 索引的创建

创建索引的方式可以大体上分为两类:

  1. 造表时创建索引
  2. 造表后创建索引

2.1 创建表时创建索引

1. 隐式创建

在使用 create table 创建表时,除了可以定义列的数据类型外,还可以定义主键约束,外键约束或者唯一性约束,这些约束在创建同时,也就创建了一个对应的索引。

比如:

create table dept(
dept_id int primary key auto_increment,
dept_name varchar(20)
);

create table emp(
emp_id int primary key auto_increment,
emp_name varchar(20) unique,
dept_id int,
constraint emp_dept_id_fk foreign key(dept_id) references dept(dept_id)
);

结果:

java stream 索引下标 java索引是从什么开始_全文索引

2. 显式创建

创建普通索引:

create table book(
book_id int,
book_name varchar(100),
authors varchar(100),
info varchar(100),
comment varchar(100),
year_publication year,
-- 声明索引
index idx_bname(book_name)
);

java stream 索引下标 java索引是从什么开始_java_02


创建由约束的索引:

create table book1(
book_id int,
book_name varchar(100),
authors varchar(100),
info varchar(100),
comment varchar(100),
year_publication year,
-- 声明索引
unique index uk_idx_comment(comment),-- 创建唯一性约束
primary key (book_id),-- 创建主键约束
index nul_bid_bname_info(book_id,book_name,info)-- 创建联合索引
);

java stream 索引下标 java索引是从什么开始_全文索引_03


注意:联合索引遵循最左前缀原则

3. 全文检索

全文索引和上面的创建方式基本一致:fulltext indec(info),但是全文索引的查询方式比较特殊:

select * from book where match(info) against (‘查询字符串’)

注意:

  1. 使用全文索引前,搞清楚版本支持情况
  2. 全文索引比起 like + % 的方式要快 N 倍,但是存在精度问题
  3. 如果需要全文索引的是大量数据。建议先添加数据,再创建索引

2.2 创建表后创建索引

1. alter table 的方式

create table book2(
book_id int,
book_name varchar(100),
authors varchar(100),
info varchar(100),
comment varchar(100),
year_publication year
);
alter table book2 add index idx_cmt(comment);-- 添加普通索引
alter table book2 add unique uk_idx_bname(book_name);-- 添加唯一性索引
alter table book2 add index mul_bid_bname(book_id,book_name); -- 创建联合索引

java stream 索引下标 java索引是从什么开始_java stream 索引下标_04

2. create index 的方式

create table book3(
book_id int,
book_name varchar(100),
authors varchar(100),
info varchar(100),
comment varchar(100),
year_publication year
);
create index idx_cmt on book3(comment);-- 添加普通索引
create unique index uk_idx_bname on book3(book_name);-- 添加唯一性索引
create index mul_bid_bname on book3(book_id,book_name);-- 创建联合索引

java stream 索引下标 java索引是从什么开始_数据库_05

3. 索引的删除

当表中要进行大量的增删改的工作时,可以考虑先将索引删除掉,等到这些工作做完之后,在将索引进行恢复。

删除索引的方式和上面2.2创建表以后创建索引的方式是对应的:

  1. alter table book drop index idx_xmt;
  2. drop index idx_cmt on book;

注意:添加AUTO_INCREMENT约束字段的唯一索引不能被删除

4. 索引新特性

4.1 支持降序索引

创建联合索引:

create table ts1(
a int,
b int,
index idx_a_b(a ASC,b DESC)
);

插入数据:

DELIMITER //
create procedure ts_insert()
begin 
     declare i int default 1;
     while i<800
     do 
          insert into ts1 select RAND()*80000,RAND()*80000;
          set i=i+1;
     end while;
     commit;
end //
DELIMITER ;

call ts_insert();

分析效率:

explain select * from ts1 order by a,b desc limit 5;

java stream 索引下标 java索引是从什么开始_java stream 索引下标_06


可以看到一共就执行了5行,如果这里不支持降序索引的话,他就会按照升序的索引进行查找,那得多慢啊.这里还由一点得注意一下,就是索引得升降序和查找数据得升降序应该对应起来:

java stream 索引下标 java索引是从什么开始_数据库_07


如果不对应得话,效率也是极低的:

java stream 索引下标 java索引是从什么开始_java stream 索引下标_08

4.2 隐藏索引

在MySQL 5.7 之前,只能通过显式的方式创建索引。此时,如果发现删除索引之后出现错误,又只能将索引创建回来,如果数据量比较大的话,这种方式就是极其小号资源的。

在MySQL 8之后,就开始支持 隐藏索引(invisible indexes),只需要将删除的索引设置为隐藏索引,是查询优化器不再使用这个索引,确定设设置为隐藏索引之后操作不受影响,就可以直接将该索引彻底删除,这种先将索引设置为隐藏索引,再删除索引的方式就是软删除

同时,你如果向验证删除某个索引之后的查询执行效率,就可以先暂时隐藏该索引。

1. 创建隐藏索引的方式

  1. 创建表时
create table book4(
book_id int,
book_name varchar(100),
authors varchar(100),
info varchar(100),
comment varchar(100),
year_publication year,
index idx_cmt(comment) invisible -- 设置comment为隐藏索引
);
  1. 创建表后
alter table book4 add unique index uk_idx_bname(book_name) inviaible;
create unique index uk_idx_bname on book4(book_name) invisible;

2. 修改索引是否隐藏

将uk_idx_bname 修改为可见状态

alter table book4 alter index uk_idx_bname visible;

注意:

当索引被隐藏之后,它的索引状态仍然会实时更新。如果一个索引被长期隐藏,那么可以先将其删除,因为索引的存在会影响 增删改 的性能