建立mysql索引的正确姿势

是否应该建立索引

是否应该在每张表 每个查询字段上都建立索引?答案是否定的
我们应该按照情况而定 如果一张表的sql语句的执行时间并不长,为什么要建立索引来增加维护表和索引的开销呢?
1.我们可以打开慢查询日志
slow_query_log=1
2.慢查询日志存储路径
slow_query_log_file=/var/log/mysql/log-slow-queries.log
3.SQL执行时间大于3秒,则记录日志
long_query_time=3

那么当我们发现这条语句执行时间过长 就立马建立索引吗?也不是的,首先我们要先判断sql语句是否可以优化:
1.尽量不要返回所有字段 select * from tablename
2.尽量不要在select中使用子查询

然后才是建立索引来优化sql

那么索引应该建立在哪些字段上呢?

以下网上搜索来的有一些规则:

1.条件查询次数比较多的字段
2.区分度比较高的字段 比如:唯一标识字段 如果是类似性别之类只有“男”和“女”就没必要添加索引了
3.经常用于连接查询的列
4.经常需要排序的列(group by / order by)
5.where子句上作为条件筛选的字段

不要在频繁更新的字段,值有非常多的字段建立索引
不要在表数据量小的情况下建立索引 因为表数据量小导致全表扫描的效率并不会比走索引低(这里默认不是主键索引需要回表的情况)
对于数据量很大或者很小的列如text, image和bit不适合建索引

建立索引的语句

create index [indexname] on tablename;`

索引设计三星准则

如果一个查询满足三星索引中三颗星的所有索引条件,理论上可以认为我们设计的索引是最好的索引。什么是三星索引
第一颗星:WHERE 后面参与查询的列可以组成了单列索引或联合索引
第二颗星:避免排序,即如果 SQL 语句中出现 order by colulmn,那么取出的结果集就已经是按照 column 排序好的,不需要再生成临时表
第三颗星:SELECT 对应的列应该尽量是索引列,即尽量避免回表查询。

什么情况下会导致索引失效呢

1.模糊查询中,like "%aa%"将会使索引失效,但是后模糊不会例如like “aa%” 具体原因是因为索引的底层实现在查找数据时会导致无法缩减查找范围
2.在索引字段是使用函数或者做运算
3.范围查找:不等于(!=或者<>),not in ,not exists 的时候有可能会导致全表扫描(原理和like一致)
4.or连接多个条件会使索引失效,除非or的条件都加了索引或者改成union all连接
5.隐式类型转换和隐式字符编码转换 都会使得索引失效。 如果id是字符类型的,1是数字类型的,你用explain会发现走了全表扫描,根本用不上索引,为啥呢?因为MySQL底层会对你的比较进行转换,相当于加了 CAST( id AS signed int) 这样的一个函数,上面说过函数会导致走不上索引。还是一样的问题,如果两个表的字符集不一样,一个是utf8mb4,一个是utf8,因为utf8mb4是utf8的超集,所以一旦两个字符比较,就会转换为utf8mb4再比较。转换的过程相当于加了CONVERT(id USING utf8mb4)函数,那又回到上面的问题了,用到函数就用不上索引了
6 is null,is not null 一般情况下也无法使用索引
7…字符串不加单引号索引失效
8.少用or或in,用它查询时,mysql不一定使用索引,mysql内部优化器会根据检索比例、表大小等多个因素整体评 估是否使用索引,详见范围查询优化
9.不满足最左前缀法则时不走索引(MySQL会一直向右匹配直到遇到范围查询 (>,<,BETWEEN,LIKE)就停止匹配。)

猜你喜欢

转载自blog.csdn.net/f_a_ker/article/details/113990126