数据库
首页 > 数据库> > MySQL(二)MySQL的索引

MySQL(二)MySQL的索引

作者:互联网

MySQL(二)MySQL的索引

索引介绍

索引是什么

​ 官方介绍索引是帮助MySQL高效获取数据的数据结构。更通俗的说,数据库索引好比是一本书的目录,能加快数据库的查询速度。

索引的优劣势

优势:

索引的分类

单列索引、组合索引、全文索引、空间索引、位图索引(oracle)

单列索引之普通索引

CREATE INDEX index_name ON table(column(length));
ALTER TABLE table_name ADD INDEX index_name(column(length));

单列索引值唯一索引

CREATE UNIQUE INDEX index_name ON table(column(length));
ALTER TABLE table_name ADD UNIQUE INDEX index_name(column(length));

组合索引

ALTER TABLE article ADD INDEX index_name_time (title(50),time(10));

删除索引

DROP INDEX index_name ON table;

查看索引

SHOW INDEX FROM table_name \G;

索引原理分析

索引的存储结构

B树和B+树数据结构实例网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

非聚集索引(MyISAM)

索引和数据是分开存储的

主键索引

主键索引是一个B+tree,tree上存的是每一行数据的地址;

在这里插入图片描述

在这里插入图片描述

辅助索引

辅助索引是一个B+tree,tree上存的是每一行数据的地址;

在这里插入图片描述

聚集索引(InnoDB)

主键索引

主键索引是一个B+tree,数据挂在主键索引上;

在这里插入图片描述

主键:

辅助索引

辅助索引是一个B+tree,主键挂在辅助索引上;

在这里插入图片描述

在这里插入图片描述

利用组合索引形成覆盖索引

可以利用组合索引完成覆盖索引,就可以不需要检索两次索引树,就可使用辅助索引完成查询。

索引的使用场景

哪些情况需要创建索引

  1. 主键自动建立唯一索引
  2. 频繁作为查询条件的字段应该创建索引 where
  3. 多表关联查询中,关联字段应该创建索引 on 两边都要创建索引
  4. 查询中排序的字段,应该创建索引,因为B+TREE 有顺序
  5. 覆盖索引 不需要回表 组合索引
  6. 统计或者分组字段,应该创建索引

哪些情况不需要创建索引

  1. 表的记录太少,索引是要有存储开销
  2. 频发更新索引需要维护
  3. 查询字段使用频率不高

索引失效

查看执行计划

explain出来的信息有10列,分别是

id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra

创建三张表来查看sql的执行计划

# --用户表
create table tuser(
id int primary key,
loginname varchar(100),
name varchar(100),
age int,
sex char(1),
dep int,
address varchar(100)
);
# --部门表
create table tdep(
id int primary key,
name varchar(100)
);
# --地址表
create table taddr(
id int primary key,
addr varchar(100)
);
# --创建普通索引
alter table tuser add index idx_dep(dep);
# --创建唯一索引
alter table tuser add unique index idx_loginname(loginname);
# --创建组合索引
alter table tuser add index idx_name_age_sex(name,age,sex);
# --创建全文索引
alter table taddr add fulltext ft_addr(addr);

insert into tuser values (1,'ls','lisi',18,1,1,'xian');
insert into tuser values (2,'zs','zhangsan',19,1,2,'xian');
insert into tuser values (3,'ww','wangwu',20,1,2,'shanghai');
insert into tuser values (4,'ll','liuliu',18,2,1,'beijing');
insert into tuser values (5,'qf','qifeng',22,2,3,'xian');
insert into tuser values (6,'bd','badang',23,1,1,'xian');

insert into tdep values (1,'ls');
insert into taddr values (1,'beijing');

explan 每个字段的含义

       表示查询中的顺序,一般会有下面三种情况
             1.id相同:执行顺序从上到下
             2.id不同:如果是子查询 id好会增大,id号越大,查询优先级越高
             3.id相同的、不同的,同时存在

索引失效分析

# 索引全值匹配:条件与索引一一对应
explain select * from tuser where name='lisi' and  age = '18' and sex='1';
# 最左前缀:如果索引了多个列,要遵守最佳左前缀法则。指的是查从索引的最左前列开始,并且不跳过索引中的列
    # 错误示范
        # 带头索引死
        explain select * from tuser where sex='1';
        # 中间索引断 (带头索引生效,其他索引失效)
        explain select * from tuser where name='lisi' and sex='1';
    # 正确示范
        explain select *from tuser where name='lisi' and age = '18' and sex = '1';
# 不要再索引上做计算
    explain select * from tuser where loginname='zs';
    # 不要进行这些操作:计算、函数、自动/手动 类型转换,不然会导致索引失效而转为全表扫描
    explain select * from tuser where left(loginname,1) = 'zs';
# 范围条件右边的列失效
    # 出现范围条件(betwee、<、>、in等),索引不能继续使用右边的值
    explain select * from tuser where name = 'lisi' and age > 18 and sex ='1';
# 尽量使用覆盖索引
    # 尽量使用覆盖索引(只查询索引的列),也就是查询列和索引列一致,减少select *
    explain select * from tuser;
    explain select name,loginname from tuser;
    # 覆盖索引
    explain select loginname from tuser;
    explain select name from tuser;
    explain select name,age,sex from tuser;
# 索引字段上不要使用不等号
    # 索引字段上使用(!= 或者 <>)判断时,会导致索引失效而转向全表扫描
    # 注:主键索引会使用范围索引,辅助索引会失效
    explain select * from tuser where name != 'lisi';
    explain select * from tuser where id != '1';
# 主键索引字段上不可以判断null
    # 主键字段上不可以使用null
        # 索引字段上使用is null判断是可以使用索引
        explain select * from tuser where name is null;
        # is not null 不使用索引
        explain select * from tuser where name is not null ;
# 索引字段使用like不以通配符开头
    # 索引字段使用like以通配符开头(‘%字符串’)时,会导致索引失效,转向全表扫描
    explain select * from tuser where name like '%l';
    explain select * from tuser where name like 'l%';
        # 使用覆盖索引可以解决这个 失效问题
        explain select name,age,sex from tuser where name like '%l%';
# 索引字段字符串要加单引号(隐式转换问题)
    # 索引字段是字符串的话,查询时不加单引号会导致全表扫描
    explain select * from tuser where loginname=1111;
    explain select * from tuser where loginname='1111';
# 索引字段不要使用or
    explain select * from tuser where name='lisi' or age = 18;

标签:tuser,explain,查询,索引,MySQL,where,select
来源: https://blog.csdn.net/qq_44621930/article/details/113826744