前言:
做服务端开发的小伙伴,在面试过程中,mysql的优化基本上是必问项,涉及到mysql优化,mysql索引又基本上是必问项。很多小伙伴在面试的时候回答不是很清楚,包括索引的类型以及使用等等。网上的很多博客也写的不清不楚。那我就自己写篇博客吧~
什么是索引?
索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据。
索引的类型和方法、使用场景
我们一般在写入频率不高,查询频率较高的表或者字段添加索引,提高查询效率。
按照索引生成选择的列可以分为:
1. 单列索引
没什么好说的。
2. 联合索引
2.1 测试的过程移步这个博客
https://www.jianshu.com/p/636a9f6d5bdc
2.2 结论
where…and语句中的联合索引几个字段的顺序可以不一致,只要包含最左的字段就可以使索引生效,因为mysql的sql优化器会优化这些代码。
2.3注意
最左字段的选择,一定要可以筛选大量数据,一定要使用的频率非常之高。 不然的话,mysql查询时候,匹配where中最左字段的条件有可能会造成全表扫描。
按照索引的使用规则可以分为:
1. 普通索引(Normal)
没什么好说的。
2. 唯一索引(Unique)
这个经常会和联合索引在一块使用,组成一个联合唯一索引。保证索引的这几个列的组合在数据库中的唯一性。(如果值是NULL则可以重复)
3. 全文索引(Full Text)
通过数值比较、范围过滤等就可以完成绝大多数我们需要的查询,但是,如果希望通过关键字的匹配来进行查询过滤,那么就需要基于相似度的查询,而不是原来的精确数值比较。大量的数据使用 like + %查询会很慢,全文索引就是为这种场景设计的。
注意:
1. MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引,以前的版本InnoDB不支持;
2. 只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。
3. 使用:
全文索引有自己的语法格式,使用 match 和 against 关键字,比如
4. 主键索引(Primary)
必须包含主键。
5. 空间索引(Spatial)
查询mysql存储的二进制数据的时候使用。
SELECT* FROM fulltext_test
WHERE MATCH(content,tag) against('xxx xxx');
索引的方法有两种:
1. BTREE
2. HASH
参考博文:https://www.yidianphp.com/archives/811
如何查看索引是否生效?
select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询时,会返回执行计划的信息,而不是执行这条SQL。通过 explain 我们可以知道以下信息:表的读取顺序,数据读取操作的类型,哪些索引可以使用,哪些索引实际使用了,表之间的引用,每张表有多少行被优化器查询等信息。
explain详解移步:https://www.cnblogs.com/butterfly100/archive/2018/01/15/8287569.html
执行以下sql:
EXPLAIN SELECT * FROM test_user;
显示结果:
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | test_user | NULL | ALL | NULL | NULL | NULL | NULL | 10 | 100.00 | NULL |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------+
我们这里简单介绍返回的几项常用的:
1. type:
这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行。
依次从最优到最差分别为:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
eq_ref指primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录
ref指普通索引被使用。
all指全表扫描
2. key:
查询中实际使用的索引,为null则没有使用索引
3. rows:
查询中mysql检测扫描的数据条数。
哪几种情况下索引会不生效?
- 查询的条件,使用索引的效果和不使用索引效果一样或者更差,则不会使用,就像前边我们提到的联合索引的使用注意事项,最左匹配的索引列如果查询范围太广,造成全表扫描,则索引会失效。
- where条件中使用OR: 这个也不用过多解释吧?因为OR是或的意思,就是说查询条件不一定会包含索引列。所以索引会失效。
- 查询条件中包含“!=”或”<>”:会造成全表扫描
- 模糊查询"%"打头:会造成全表扫描