优缺点
优点
大大提高查询速度
通过创建唯一索引,可以保证数据库每一行数据的唯一性
可以加深表与表之间的连接
可以显著减少查询中分组和排序的时间
缺点
创建索引和维护索引需要时间,而且数据量越大时间越长
创建索引需要占磁盘空间,如果有大量索引,可能比数据文件更快达到最大文件尺寸
当对表中的数据进行增加、修改、删除的时候,索引也要同时维护,降低了数据的维护速度
索引创建规范
单张表索引数量不超过5个,单个索引中的字段不超过5个
表必须有主键,推荐使用自增字段作为主键(自增id、雪花算法等)
<font color="#212121">禁止冗余索引(索引|(a,b,c),索引|(a,b)),禁止重复索引(索引|(a),索引|(a,主键ID))</font>
联表查询时,join列的数据类型必须相同,并且要建立索引
不在低基数列建立索引,如性别
选择区分度大的列建立索引,组合索引中,区分度大的放前面
合理创建组合索引(a,b,c)相当于(a),(a,b),(1,b,c)
合理使用覆盖索引减少IO跟避免排序
索引优化分析
EXPLAIN SELECT * from ** WHERE *** =****
执行计划字段解释
id:编号
id值相同,从上往下 顺序执行
id值越大越优先查询 (本质:在嵌套子查询时,先查内层 再查外层)
select_type :查询类型
SIMPLE
简单查询(不包含子查询、union)
PRIMARY
包含子查询SQL中的 主查询 (最外层)
SUBQUERY
包含子查询SQL中的 子查询 (非最外层)
table :输出结果集的表
type :访问类型
从左到右,性能由好到最差,system>const>eq_ref>ref>range>index>all (ref到range之间还有一些其他的不过不太常见)(要对type进行优化的前提:有索引)(一般优化后的type必须在range以上)
分类
system
只有一条数据的系统表 ;或 衍生表只有一条数据的主查询(基本不能达到可忽略)
const
仅仅能查到一条数据的SQL ,用于Primary key 或unique索引 (类型 与索引类型有关)
eq_ref
唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多 、不能0)
ref
非唯一性索引,对于每个索引键的查询,返回匹配的所有行(0,多)
range
检索指定范围的行 ,where后面是一个范围查询(between ,> < >=, 特殊:in有时候会失效 ,从而转为 无索引all)
possible_keys :可能用到的索引
key :实际使用的索引
key_len :实际使用索引的长度
用于判断复合索引是否被完全使用 (a,b,c)
demo
在utf8编码中:1个字符占3个字节,如果索引的字段可以为null,则会使用一个字节用来标识 ,如果是varchar这种,会用两个字节表示可变<br><br>例如 :某个字段 name(varchar(20)),如果用到了这个字段的索引那么lenth就是 20*3+1(null)+2(可变字符) =63
ref :表之间的引用
rows: 被索引优化查询的 数据个数 (实际通过索引而查询到的 数据个数)
Extra :额外的信息
using index
性能提升; 索引覆盖(覆盖索引)。原因:不读取原文件,只从索引文件中获取数据 (不需要回表查询)只要使用到的列 全部都在索引中,就是索引覆盖using index
using where
表示进行了回表查询
using filesort
性能消耗大;需要“额外”的一次排序(查询) 。常见于 order by 语句中。
using temporary
性能损耗大 ,用到了临时表。一般出现在group by 语句中。
impossible where
where子句永远为false
避免索引失效的一些原则
复合索引,不能跨列使用(index(a,b,c),你的索引使用就不要 where a=x,c=x)
复合索引尽量使用全索引匹配
不要在索引上进行任何操作(计算,函数,类型转换),否则索引失效
复合索引不要使用不等(!= ,<>,>),这样会导致自身以及右侧的索引失效**(这个不是一定的有概率的**)
like尽量以“常量”开头,不要以'%'开头,否则索引失效
尽量不要使用or,否则索引失效(字段都是单值索引是可以的)
常见问题
为什么我们经常被要求,只查询需要的字段?
在例如你查询只用到name时,select * from user where iphone=xxx,索引为(iphone,name)的时候,我们根据上面的innodb的索引结构学习到,你要查询索引中没有的字段的时候,需要先通过辅助索引找到主键索引的值,然后再找到对应的数据值(过程叫做回表),这样就多了I/O操作,如果你的sql改成select name from user where iphone=xxx,这个name值在辅助索引中已经有了,所以不需要再去主键索引中找数据,就提高了查询效率(这种情况叫做覆盖索引)
经常在数据量很大的情况下我们要把主键用整数代替字符串,并且是增长的?
在使用BigInt的时候比UUID(为保证不重复一般都是UUID),占用的字节少,那么在B+Tree的结构中,就能存储更多的值。
比字符串好排序
如果你生成的是自增的(分布式id生成策略中都是增加的),在插入时,就可以尽可能减少页分裂