目录
概念
用于提高查询效率的数据结构,在默认的存储引擎中采取的数据结构为B+tree 创建索引虽会提高查询效率 但是会提高内存空间 是一种空间换时间的优化方式
使用场景
在大量数据以及高频率查询的情况下,可以对该表的字段创建索引,以此达到查询优化的效果
相关语法
查看索引
select index from tableName;
新增索引
create index [unique | fulltext] index indexName on tableName (columnName1,...);
-- 当前语法可以创建单列索引 填写多个字段后即可构建多列索引
删除索引
drop index indexName on tableName;
使用指定索引
select * from tableName use index(indexName) where condition;
//indexName 表示索引的名称 condition表示条件
这种人为干扰的情况下一般出现在查询字段中即存在于联合索引中 同时也单独具备一个单列索引
这种时候如果只有一个字段的话 就可以认为干涉的使用单列索引
强制使用指定索引
select * from tableName force index(indexName) where condition;
//同上 但是为强制使用
使用规则
extra字段存在的值
extra字段是通过explain关键字查询SQL语句的索引使用情况返回的表的字段
#### NULL: 没有用到额外的附加条件
#### Using filesort:查询语句中包含了oder by语句,索引无法完成排序,数据量小的时候在内存中完成排序,否者在磁盘中完成排序。
#### Using temporary:使用到了临时表。
#### Using Index:使用覆盖索引进行数据返回(Innodb引擎才存在),不会进行回表查找。
#### Using Where:查询语句中存在where范围查找,会回表查找数据。
#### Using Where Using Index:覆盖索引中存在范围查找,但是也不会进行回表,直接在索引上就能拿到数据。
#### Using Index Condition:跟Using Where Using Index有一些差别,它的查找用到了联合索引,查找的数据有不在索引中的字段,所以会进行回表查找数据。
最左前缀法则
最左前缀法则在联合索引中会出现,当使用联合索引时 必须确保联合索引的最左字段会被使用 否则索引失效 如果跳过了某一列 索引将部分失效 联合索引的创建也将依照最左前缀法则去构建 最左前缀法则只要确保在执行SQL语句的时候条件中包含最左字段即可 这和最左字段在条件中的所在顺序没有关系
假设我创建了一个联合索引 该联合索引的字段从左到右为phone name age;
select phone,name from tb_user where phone='17812345689' and name = '张三';
那么如果返回的列中都包含在索引中的话,那么该语句满足联合索引的最左前缀法则 且不会触发回表查询
注意
当联合索引的最左字段使用了like语句 无论是前部模糊还是尾部模糊 都有几率触发全表查询
可以通过在select 前面添加explain关键字查看该SQL语句的索引使用情况 如果在extra该列中出现了using where
那么就表示该语句中使用了全表扫描
explain select phone,name from tb_user where phone like '178123%' and name = '张三';
索引失效情况
1.联合索引不满足最左前缀法则
2.使用运算符操作索引字段 (这将导致和B+tree树的不匹配 从而无法触发索引)
3.索引字段为字符串类型 在操作的时候不加引号
4.索引字段使用模糊查询 但是采取的是前部模糊查询 而非尾部模糊查询 前部则索引失效 尾部则不然
5.使用or进行条件筛选,or的前面使用了索引字段 而后面没有使用 则索引失效
6.如果MySQL的评估表示全表扫描的效率高于索引 那么就不会使用索引
or的索引失效情况
select * from tb_user where id = 2 or age =23;
//在该语句中id为聚集索引 而age为联合索引 联合索引需要遵守最左前缀法则 而age非最左字段 所以单独使用不具备索引的条件 也就是说在上述的SQL语句中只有id的聚集索引被使用了 所引整条SQL语句的索引调用失效
覆盖索引
所谓覆盖索引就是尽量避免select *的情况
也就是说最终的返回字段不是 * 而是索引中的字段 并且返回的字段在索引中全部具有 这样就会避免回表查询 提高查询效率
假设我创建了一个联合 从左至右为phone name age
select id,phone,name,age from tb_user where id=20;
//这里就通过id这个聚集索引完成了SQL查询 通过explain关键字即可查出该语句的索引执行情况为null 即不触发回表查询
前缀索引
当字段类型为字符串类型的时候,如果直接使用该字段创建索引的话,那么就将占用大量的磁盘空间,会占用大量的内存空间 严重影响查询效率。此时就可以使用前缀索引,即只存储一部分前缀作为索引
前缀索引的创建语法
create index indexName on tableNam(columnName(n));
//n表示截取的前缀长度
前缀长度的选择
select count(distinct substring(column,start,end)) / count(*) from tableName;
//column 表示需要设置前缀索引的字段
//start 表示截取的的起始值
//end 表示截取的长度
当得出的值为1或者最接近1则该start和len的截取范围的内容是最佳的前缀索引
单列索引和联合索引
单列索引:即一个索引只包含单个列
联合索引:即一个索引包含了多个列
在业务场景中,如果存在多个查询条件,建议建立联合索引 以此规避回表查询。
联合索引不仅可以是联合默认索引 也可以是联合唯一索引(unique)
设计原则
1.针对数据量较大,且查询操作比较频繁的表建立索引
2.针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引
3.尽量选择区分度高的列作为索引(例如身份证号 手机号等),尽量建立唯一索引,区分度较高,使用索引的效率较高
4.如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引
5.尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率
6.要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率
7.如果索引列不能存储null值,请在创建表时使用NOT NULL约束它 当优化器知道每列时候包含NULL值时,它可以更好的确定哪个索引的效率最高