mysql进阶知识-索引2

”种一棵树最好是十年前,其次是现在“,结合个人十多年IT基础架构领域摸爬滚打的经验来看,数据库领域潜力无限,大有可为。运维领域知识面需要广,更需要专,数据库是我选择做专做深的方向。

今天继续来跟大家聊一聊关于索引的性能分析,使用规则,设计原则方面的知识,至此索引方面的知识就分享完毕了

索引知识概览

索引

性能分析工具

  1. 执行频次查看

#查看增,删,改,查执行频次:

#查看全局
show global status like “Com_______”;

#查看当前session
show session status like “Com_______”;
  1. 慢查询日志

默认执行时间超过10s的增删改查语句,都会被记录到日志中,默认不开启,需要在/etc/my.cnf配置文件中开启

#开启慢查询日志开关
slow_query_log=1
#设置慢查询日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志中
long_query_time=2

需要重启mysql使配置生效,日志位置:/var/lib/mysql/{hostname}-slow.log

查询慢查询是否开启:show variables like “slow_query_log”

  1. profile详情
#版本是否支持
select @@have_profiling;
#profile是否开启
select @@profiling;
#开启profile
set profiling = 1;
#查看所有语句的耗时
show profiles
#查看指定sql语句的详细耗时
show profiles for query query_id;
#查看指定sql语句的cpu开销
show profiles cpu for query query_id;
  1. explain

一条SQL语句除了要知道它整体运行耗时之外,我们还需要了解它内部的运行详细细节,这时就需要请出explain这个工具登场了。

explain的作用:能够把一条大SQL语句详细拆解成一条条子语句,然后展示每条子语句的执行优先顺序,以及连接类型等信息

语法:

直接在select语句前加上explain或desc

查询结果各字段含义:

id:查询结果子句的序号,id越大越先执行,id相同顺序执行

select_type:查询类型,常见的有simple,primary,union,subquery

type:查询类型, 性能由好到差依次为:NULL(不查任何表)、system(查询系统表)、const(主键或唯一索引)、eq_ref、ref(非唯一索引)、range、index(遍历整个索引树)、all(全表扫描)

possible_key:可能用到的索引

key:实际用到的索引

key_len:索引长度

rows:返回的行数

filtered:返回的行数占查询行数的百分比,值越大越好

extra:额外信息

红线红框部分需要重点关注

使用规则

  1. 最左前缀法则

多列都属于同一个索引名称情况下,遵循最左前缀法则。查询从最左列开始,不能跳过索引中的列(只要最左列存在即可)。

如果跳过最左列,则索引失效,如果跳过中间列,则后面的列索引失效。

验证例子(使用explain):

范围查询右侧的列索引失效(第二条是解决方案)

  1. 索引失效情况
在索引列上进行运算操作,索引将失效。
例如:explain select * from tb_user where substring(phone, 102) = '15';

字符串类型使用时不加引号,索引将失效。
例如:explain select * from tb_user where phone = 17799990015;

模糊查询中,仅仅匹配尾部,索引不会失效。但是匹配头部,索引则会失效。
例如:explain select * from tb_user where profession like '%工程';

用or分割开的条件,其中有一列没用索引,那么整体索引都不会用到

查询表中的数据量,MYSQL评估全表扫描比索引快,则放弃使用索引
  1. SQL提示
sql提示是非常重要的一种优化手段,可以人为的指定/忽略使用哪个索引。

例如,建议使用索引(最终由mysql决定):

explain select * from tb_user use index(idx_user_pro) where profession="软件工程";

不使用指定索引:

explain select * from tb_user ignore index(idx_user_pro) where profession="软件工程";

强制使用指定索引:

explain select * from tb_user force index(idx_user_pro) where profession="软件工程";
  1. 覆盖索引&回表查询

尽量使用覆盖索引(查询使用到了索引,并且查询返回的列都在索引中能找到),如下图:

在辅助索引中无法查到时,需要到聚集索引中查,这就是回表查询(性能比覆盖索引差,查询了两次),如下图:

面试题:

一张表,有四个字段(id, username, password, status),由于数据量大,需要对以下SQL语句进行优化,该如何进行才是最优方案:
select id, username, password from tb_user where username='itcast';

解:给username和password字段建立联合索引,则不需要回表查询,直接覆盖索引
  1. 前缀索引

碰到类似text类型的字段,需要建立索引的情况。由于该类型字段占用空间太大,不能直接整个建立索引,需要截取固定长度的前缀做索引。从而节约索引空间,提高索引效率。

这里有一个问题:如何确定前缀截取长度呢?可以通过不重复记录数和总体记录数的比值来确定,数值越高,查询准确率越高。 例如: select count(distinct email) / count(*) from tb_user;

有些场景需要考虑截取长度,则需要降低选择性数值 列如: 这种场景截取长度选择5则是最优解

  1. 单列索引&联合索引

顾名思义单列索引是只对一列建立索引,联合索引则是对多列建立索引。

使用场景:大部分查询语句都需要查询多列数据,为了提高查询效率,减少回表查询次数,则需要使用联合索引,并手动指定使用自己创建的联合索引

如下:默认mysql不会使用用户创建的联合索引,需要手动指定

索引设计原则

1.对于数据量较大(100万条以上),且查询比较频繁的表需要建立索引

2.常作为查询条件(where),排序(order by),分组(group by)的字段建立索引

3.选择区分度高的列建立索引,尽量使用唯一索引。区分度越高,索引效率越高

4.如果是字符串或者文本类型的字段,可以根据字符串的特点,建立前缀索引

5.尽量使用联合索引,避免单列索引。可以节省存储空间,避免回表查询,提高查询效率

6.要控制索引的数量,索引越多维护索引结构的代价就越大,会影响增删改的效率

7.如果索引列不能存储NULL值,需要在建表时使用NOT NULL约束,便于优化器知道用户哪个索引最有效

作者:谷会于(转载请获本人授权,并注明作者与出处)

本文使用 文章同步助手 同步

你可能感兴趣的:(mysql进阶知识-索引2)