数据库的索引

本文介绍了数据库索引的重要性,何时使用索引,以及如何创建和删除索引。详细讲解了索引的分类,如B+树、Hash、全文和R树等,并探讨了索引失效的情况。同时,还深入讨论了索引的存储结构,包括聚集和非聚集索引,以及索引回表和覆盖索引的概念。

目录

一、为什么要用索引

二、什么时候才用索引

三、创建删除索引

1)创建索引

2)删除索引

四、索引分类

1)按数据结构分类

1.B+树索引

2.Hash索引

3.全文索引(倒排索引)

4.R树空间索引

2)按字段个数分类

1.单列索引

2.组合索引(复合索引、联合索引)

3)按物理存储分类

1.聚簇索引

2.非聚簇索引(二级索引、辅助索引)

五、索引失效

1)Like

2)or

3)索引列计算,不走索引

4)索引列用函数,不走索引

5)索引列用!=,不走索引

六、索引的存储结构

1)概述

2)聚集索引存储结构的例子

3)聚集索引和非聚集索引存储结构的综合例子

4)索引回表

1.定义

2.例子

3.解决办法

5)索引覆盖


一、为什么要用索引

索引就好比是一本书的目录,能快速定位数据。为了提高查询效率,减少查询时间

二、什么时候才用索引

1.数据量庞大;

2.经常出现在where的后面,以条件的形式存在,也就是说这个字段总是被扫描;

3.该字段很少DML(insert delete update)操作(因为DML之后,索引需要重新排序。索引越多,增删改越慢);

注意:建议不要随意添加索引。索引也是需要维护的,太多的话反而会降低系统的性能。

三、创建删除索引

1)创建索引

创建主键索引:创建或设置主键字段时,自动创建索引

创建唯一索引:create unique index 索引名 ON 表名(字段);

创建普通索引:
create index 索引名 on 表名(字段);   //索引创建在字段上

alter table 表名 add index 索引名(字段);  //修改表时添加

创建组合索引:create index 索引名 on 表名(字段1,字段2);

2)删除索引

drop index 索引名 on 表名;

四、索引分类

1)按数据结构分类

1.B+树索引

二叉树:完全二叉树 、满二叉树 、二叉搜索树(又叫二叉排序树、二叉查找树) 、平衡二叉树 ( 又叫AVL树)、红黑树、堆、哈夫曼树(又叫最优二叉树)、线索二叉树

多叉树:B树(又叫多路平衡查找(搜索)树)B+树B*树)

2.Hash索引

mysql的Memory存储引擎,默认是 Hash索引。

3.全文索引(倒排索引)

使用like '%xxx%'进行模糊查询时,字段的索引就会失效。因此,在数据量大的情况下,通过此种方式查询的效率极低。这个时候,就可通过全文索引(Full-Text Search)来进行优化。

全文索引主要对字符串类型建立基于分词的索引,只有char、varchar,text 列上可以创建全文索引,以便能够更加快速地查询数据量较大的字符串类型的字段。

注意,MySQL 5.6之前,只有MyISAM支持全文索引。MySQL 5.6后MyISAM、InnoDB都支持。

使用语法可以参考:mysql全文索引_明豆的博客-优快云博客_mysql全文索引

4.R树空间索引

对空间数据类型的字段建立的索引。空间索引只能在存储引擎为myisam的表中创建,mysql中的空间数据类型有4种,分别是geometry、point、linestring、polygon。创建空间索引的列,必须将其声明为not null

2)按字段个数分类

1.单列索引

(1)主键索引

特殊的唯一索引,建立在表的主键字段,不能为null。(如果没有主键,则该表的第一个唯一非空索引作为聚集索引。如果没有主键,也没有合适的唯一索引,InnoDB会生成一个隐藏的主键列作为主键索引)

(2)唯一索引

当某个列添加了Unique约束,会创建唯一索引。每列值必须唯一不能重复,可以为null。

(3)普通索引

给普通字段添加的索引。

(4)前缀索引

对字符串或二进制类型字段前几个字符或几个byte建立索引

2.组合索引(复合索引、联合索引)

多个字段合起来创建一个索引。组合索引遵循最左前缀匹配原则

最左前缀匹配原则:

(1)条件

组合索引的第一个字段必须出现在查询组句,组合索引才会被用到;

(2)匹配规则

检索数据从组合索引的最左边开始匹配。

(3)例子

1.建索引

对列字段1、列字段2和列字段3建一个联合索引:

create index 索引名 on 表名(字段1,字段2,字段3);

2.实际创建3个索引

联合索引实际建立了(字段1)、(字段1,字段2)、(字段1,字段2,字段3)三个索引。

3.排序规则

select * from 表名 where 字段1=1 and 字段2=2;  //语句1

select * from 表名 where 字段2=2 and 字段1=1;  //查询优化器会优化成语句1

检索时使用索引(字段1,字段2)进行数据匹配。首先会对最左边的字段1的数据排序,然后再对字段2排序。相当于执行了“order by 字段1,字段2”。

4.匹配特点

索引中所有列通过"=" 或 “IN” 进行精确匹配时,索引都可以被用到

遇到范围查询(>、<、between、like)就会停止匹配

select * from 表名 where 字段1>1 and 字段2=2;   //a字段走索引(有序),b全表扫描(无序)

select * from 表名 where 字段1>1 and 字段2>2 and 字段3=3;   //a、b字段走索引(有序),c无序全表扫描(无序)

3)按物理存储分类

1.聚簇索引

(1)记录和索引物理顺序一致(即索引的排列顺序和表数据的排列顺序一致),索引和对应行挨着存放;

(2)聚集索引就是主键索引,建立在表的主键上。如果主键是联合主键,则为组合索引;

(3)一张表只包含一个聚集索引;

(4)查询快;

(5)更新慢。因为要保持表中记录和索引的物理顺序一致,在插入新记录的时候就会对索引重新做一次排序

2.非聚簇索引(二级索引、辅助索引)

(1)记录和索引物理不连续,而是逻辑上连续,索引和对应行不存放在一起;

(2)索引建在主键以外的列上;

(3)一张表可以有多个非聚集索引;

(4)查询慢,因为回表(见第六点,索引的存储结构)

(5)更新快。因为不需要维护表记录和索引的物理顺序一致,逻辑一致就行了

五、索引失效

1)Like

select * from 表名 where name like '张%'  //走索引

select * from表名 where name like '%三丰'  //不走索引

select * from 表名 where name like '%三%'  //不走索引

2)or

select * from 表名 where name= '张三' or  age= 18  //走索引(or左右所有条件字段都有索引,才走索引)

select * from 表名 where name= '张三' or  course='历史'  //不走索引

补充说明:用or可能不走索引,因此尽量用union联合查询代替or

3)索引列计算,不走索引

select * from 表名 where age = 10+8  //走索引

select * from 表名 where age + 8 = 18  //不走索引

4)索引列用函数,不走索引

select * from 表名 where  concat('name','丰') ='张三丰';    //走索引

select * from 表名 where name = concat('张三,'丰');    //不走索引

5)索引列用!=,不走索引

select * from student where age != 18    //不走索引

六、索引的存储结构

索引的存储结构部分参考了文章:【MySQL】索引优化中的最左前缀原则和索引下推 - 灰信网(软件开发博客聚合)

1)概述

索引每个叶子节点分为索引区和数据区。

聚集索引:索引区存储主键值,数据区存储除了主键值外当前行数据

非聚集索引:索引区存储当前列值,数据区存储对应主键值

2)聚集索引存储结构的例子

 

3)聚集索引和非聚集索引存储结构的综合例子

表包含主键列ID(上有聚集索引)、普通列K(上有非聚集索引)。

insert into T values(100,1,'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

下图为该表的索引结构:

ID上的索引为聚集索引,存储主键值、除主键外当前行数据;

K上的索引为非聚集索引,存储当前列的值、对应主键值。

4)索引回表

1.定义

非聚集索引只存储当前列的值、列所在行对应的主键值,不存储所在列对应行其它列的数据。当查询条件是索引对应列,使用到了该索引,但是返回列表包含除了索引对应列的其他列。那么,执行查询,第一次只能通过主键值找到聚集索引 , 第二次再通过聚集索引才能找到需要的其他列数据;

2.例子

例1:

假如表有一个索引在name字段上:

select name,age from user where name='张三';  //要回表,因为返回列表包含其他列age

例2(还是根据上图)

在 k 索引树上找到 k=3 的记录,取得 ID = 300;

再到 ID 索引树查到 ID=300 对应的 R3;(回表1次)

在 k 索引树取下一个值 k=5,取得 ID=500;

再回到 ID 索引树查到 ID=500 对应的 R4;(回表第2次)

在 k 索引树取下一个值 k=6,不满足条件,循环结束。

3.解决办法

使用覆盖索引(覆盖索引是select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引包含覆盖)。

刚才的例子,只用把name和age建立联合索引,就实现了覆盖索引。

5)索引覆盖

如果执行的语句是 select ID from T where k between 3 and 5,这时只需要查 ID 的值,而 ID 的值已经在 k 索引树上了(辅助索引树的结点数据区存的是其对应的主键值),因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面,索引 k 已经“覆盖了”我们的查询需求,我们称为索引覆盖。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值