文章目录
- 什么是索引
- 索引的优缺点
- MySQL中的索引
- 单列索引
- 组合索引
- 全文索引
- 空间索引
- innoDB存储下的索引分类
- 回表查询
- 添加索引的SQL语句
- 索引的数据结构
- 索引提高速度原理
- 最左前缀原则
- 注意事项
什么是索引
索引是一种用于快速查询和检索数据的数据结构。
mysql中的索引结构有: B+树和Hash。
索引相当于目录的作用,使查找更加迅速
索引的优缺点
优点
- 通过减少索引的数据量来加快索引的检索速度。
- 通过索引对数据进行排序,降低数据排序成本,减少cpu消耗。
缺点
- 创建和维护索引需要耗费额外时间,使更新表的时候会变慢。
- 占用物理存储空间。
MySQL中的索引
单列索引
单列索引中包含普通、唯一、主键、前缀这四个索引。一个索引只包含一个列,但一个表中可以有多个单列索引。
- 普通索引:
普通索引的唯一作用:快速查询数据。
一张表允许创建多个普通索引,允许数据重复与 NULL。 - 唯一索引:
索引列中的值必须是唯一的,但是可以为空值。 - 主键索引:
特殊的唯一索引,不允许有空值。 - 前缀索引:
前缀索引只适用于字符串类型的数据。
前缀索引是对文本的前几个字符创建索引,相比于普通索引建立的数据更小,因为只取前几个字符。
组合索引
在表中的多个字段组合上创建的索引。
只有在查询条件中使用了这些字段的左边字段时,才会调用索引。组合索引遵循最左前缀集合。
全文索引
为了检索大文本数据中的关键字信息,是目前搜索引擎数据库使用的一种技术。
空间索引
对空间数据类型的字段建立的索引。使用SPATIAL
关键字。
空间数据类型:GEOMETRY POINT LINESTRING POLYGON
innoDB存储下的索引分类
分类 | 含义 | 特点 |
聚集索引(Clustered Index) | 将数据存储与索引放在一起,索引结构的叶子节点保存了行数据 | 有且仅有一个 |
二级索引(Secondary Index) | 将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键 | 可以有多个 |
聚集索引选取原则:
- 如果存在主键,主键索引为聚集索引
- 如果不存在主键,将使用第一个唯一索引
- 如果表没有主键,或没有合适的唯一索引,自动生成一个
rowid
作为隐藏的聚集索引。
回表查询
由于数据 innodb 底层是 b+ 树实现的, 所以查询的时候会通过二叉树的查找模式来进行查找。b+ 树的每个叶子节点都会存放数据,而二级索引存放的是这行数据的id值, 所以拿到 id 后,需要在查找一下聚集索引。聚集索引的叶子节点存放的是这行数据的所有信息.。
这个行为也称为:回表查询。
添加索引的SQL语句
- 主键索引 -
PRIMARY KEY
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
- 唯一索引 -
UNIQUE
ALTER TABLE `table_name` ADD UNIQUE ( `column` )
- 普通索引 -
INDEX
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
- 全文索引 -
FULLTEXT
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
- 多列索引
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
索引的数据结构
- 哈希索引
对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。 - BTree树索引
是一种很普遍的数据库索引结构。其特点是定位高效、利用率高、自我平衡,理论上,使用Btree在亿条数据与100条数据中定位记录的花销相同。
索引提高速度原理
mysql的存储形式是页, 在没有使用索引时:
- 定位到记录所在的页:需要遍历双向链表,找到所在的页;
- 从所在的页内中查找相应的记录:由于不是根据主键查询,只能遍历所在页的单链表了,这种查找时间复杂度为
当添加索引后::将无序的数据变成有序(相对),通过 “目录” 就可以很快地定位到对应的页上(二分查找,时间复杂度近似为)
最左前缀原则
如 User 表的name
和city
加联合索引就是(name,city)
,而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:
select * from user where name=xx and city=xx ; // 可以命中索引
select * from user where name=xx ; // 可以命中索引
select * from user where city=xx ; // 无法命中索引
例如组合索引,组合索引的生效原则是
从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用;
比如
-
where a=3 and b=45 and c=5
这种三个索引顺序使用中间没有断点,全部发挥作用; -
where a=3 and c=5
这种情况下就是断点,发挥了效果,没有效果; -
where b=3 and c=4
这种情况下就是断点,在后面的索引都没有发挥作用,这种写法联合索引没有发挥任何效果; -
where b=45 and a=3 and c=5
这个跟第一个一样,全部发挥作用,只要用上了就行,跟写的顺序无关
注意事项
- 经常需要搜索的列上,可以加快搜索的速度;
- 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
- 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
- 对于中到大型表索引都是非常有效的,但是特大型表的话维护开销会很大,不适合建索引。
- 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;
- 避免
where
子句中对宇段施加函数,这会造成无法命中索引。 - 在使用 InnoDB 时使用与业务无关的自增主键作为主键,即使用逻辑主键,而不要使用业务主键。
- 删除长期未使用的索引