1.什么是索引
索引是一个存储在磁盘中的数据,在MySql中,索引的数据结构为B+数,目的是为了方便查询,索引相当于就是数据库表的一个目录,我们可以根据目录很快的查询到数据,但是也有弊端。我们在插入数据的时候,或者更新索引字段的时候,对应的索引也会更新。
2.怎么创建,查询,删除索引
查看索引:SHOW INDEX FROM 表名称 删除索引:DROP INDEX 索引名称 FROM 表名称 创建索引:CREATE [索引类型,非必填,可以写UNIQUE代表是唯一索引,那么数据就不可以重复,写FULLTEXT意味着是全文索引,不写默认是常规索引] INDEX 索引名称 ON 表名称(字段名...可多字段) 例如:CREATE INDEX OK ON USER(sex) 不要没事乱加引号,会报错
3.索引的分类
主键索引(只能有一个) 唯一索引(可以多个) 常规索引(可以多个) 全文索引(可以多个)
5.什么字段适合使用索引
经常需要充当过滤条件的数据,并且重复率低的数据。例如ID,身份证号码,手机号码。像年龄,性别这种重复率很高的数据,就没有建立索引的必要。
6.索引在什么时候会失效
- 首先我们需要知道索引的
最左前缀法则 ,当我们的索引关联了多个字段,那么就称为联合索引,比如我创建了一个索引关联了ABC三个字段。CREATE INDEX OK ON USER(A,B,C) 。那么我在查询的时候。就需要出现条件A,才会触发索引,接着是B才会触发B索引,如果我的查询条件只有AC,跳过了B,那么只有A生效,C索引不生效。注意 SELECT * FRIM USER WHERE A=? AND C=? AND B=? 最左前缀只判断有无,和查询条件出现的顺序无关,我这条SQL查询的顺序为ACB,一样可以触发ABC三个索引。因为条件都出现了 - 在索引列上进行函数运算,索引失效,例如:
SELECR * FROM USER WHERE substring(in,0,1) = '10' - 字符串类型查询不加引号,索引失效
- 模糊查询,左模糊,索引失效,例如:
SELECR * FROM USER WHERE NAME LIKE '%锦哥' ,只有左模糊会失效,右模糊不会,当然全模糊索引也会失效 - 在SQL中有存在OR连接的,如果有一个字段没索引,那么索引全部失效
- 内部优化器如果发现走了索引还不如不走更慢,也会直接不走索引。例如我数据库中全部人的age字段都大于10岁,我们查询age大于10的SQL,会发现查询出了很多数据,而索引只有年龄字段,我们还会增加一个回表查询的操作,效率还不如全表扫描,这时候内部优化器会直接走全表扫描。
7.SQL提示
有一个很有趣的现象,假如我们创建了联合索引ABC,我们又对A创建单一索引。那么一下SQL会用到那个索引呢?SELECT A FROM USER WHERE A = 'giao' 实际上,SQL优化器会为我们自动选择。那很明显,这个SQL走单一索引肯定效果更好,这时候我们就需要让SQL优化器停手,听我们的指挥,走我们选择的索引。一共有三个方案
- 建议走这个索引(但是优化器可能不听你的建议)
SELECT * FROM USER use index('索引名称') WHERE A = 'giao' - 不允许走这个索引
SELECT * FROM USER ignore index('索引名称') WHERE A = 'giao' - 必须走这个索引
SELECT * FROM USER forceindex('索引名称') WHERE A = 'giao'
8.覆盖索引
前面我们讲到了联合索引,我们可以针对ABC多个字段创建索引。所以,我们查询的时候,就不要SELECT * ,最好是直接SELECT A,B,C。这其实很好理解,我们说了,索引就相当于目录,如果我们想找的东西在目录上就有了,那么就不需要在翻到字典里面去查询了,那如果我们通过目录,即通过索引快速定位到了数据的位置,但是数据不够,就需要翻开具体的那一页去查看数据,那么这个操作就叫做回表。
9.前缀索引
有一个有趣的问题,如果有一个字段它的内容是一篇文章。如果我们需要对这个字段创建索引,那么这个索引的体积必然十分庞大,对于系统而言可能得不偿失,这时候我们就可以对于这种超长的字段截取部分字符来做索引。例如我只取文章的前面30个字来做索引,那么体积将大大缩小。语法如下: CREATE [索引类型,非必填,可以写UNIQUE代表是唯一索引,那么数据就不可以重复,写FULLTEXT意味着是全文索引,不写默认是常规索引] INDEX 索引名称 ON 表名称(字段名(截取的数字)) 如:CREATE INDEX OK ON USER(A(10)) 但随之而来又有一个问题,我们怎么知道取10个还是5个还是100个最好呢。这里涉及到一个计算。如果我们只取前面10位数就可以让全部数据不重复,那么不就意味着取到10就是最节约空间了吗。 所以有以下公式:对字段截取X长度之后之后的数据进行去重 / 表A全部数据 = 1 ,不断的减小X的数据,直到小于1,那么小于1之前的这个截图长度就是最小的截取范围。 SELECT COUNT(DISTINCT substring(目标字段,1,X))/COUNT(*) FROM USER 当然,这个比例也不是一定要等一1,只是说可以用最小的截取范围就可以取到最佳的截取长度。在有些时候,我们可以只需维持重复率在0.9即可,那么就可以在砍掉一些长度。例如我们对手机号码字段进行取前缀索引,我们默认都是11位的手机号码。如果我们只取第一位,那么重复概率就会非常高,因为基本都是1。那如果取得是前三位,就会大大降低重复率。这个截取长度以及重复率需要根据具体的业务去规定。
10.什么是回表
前面我们多次说到回表的概念,那么什么是回表呢?下面通过简单的图文给大家简单的说明一下。如果我们的表有主键,那么就有了唯一的主键索引,也叫做:聚集索引 ,他会将索引与每一行的数据放在同一个地方存储,有且仅有一个。
可以看到,我们根据主键ID生成了一个B+数,每个叶子节点都是主键ID,主键ID下面都挂载着当前行数据。而对于普通的索引,叶子节点下则不会挂载行数据,而是挂载着主键ID,那么问题就来了,如果我们是SELECT NAME 很明显,NAME字段在索引上就有了,我们直接获取到了数据,就可以直接返回结果集,那如果我们是SELECT * 很明显,数据量不够,这时候就需要拿着我们查询到的ID,再去聚集索引 上一一匹配数据,这个过程就叫做回表查询。通过这个回表查询也解释了上面几个问题。例如为什么要覆盖索引。如果我们查询的是SELECT NAME,GENDER 两个字段,这个时候无论你创建哪一种单一索引,都会回表查询,所以效率最高的就是创建NAME,GENDER 的联合索引,避免回表查询。
12.索引设计原则
- 针对于数据量较大,且查询比较频繁的表建立索引。
- 针对于常作为查询条件(where)、排序(orderby)、分组(groupby)操作的字段建立索引。
- 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
- 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
- 尽量使用联合索,减少单列索,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
- 控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
- 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。
|