MySQL 字符集不一致导致索引失效的一个真实案例

字符集


大家好,我是只谈技术不剪发的 Tony 老师。今天给大家分析一个由于 MysqL 字符集不一致导致索引失效的案例。

问题描述

有个朋友给我发来一个问题,说是他们的系统有几十万用户,某个查询需要 5 秒以上的时间才能返回,同时服务器 cpu 资源占用率将近 100%。这个对于用户的线上操作影响非常大,那么我们就来看看如何分析和解决这个慢查询问题。

为了便于说明问题,我们对表结构进行了简化:

create table customer(
  cid int auto_increment primary key,
  cname varchar(50) not null,
  register_time datetime not null,
  recommender varchar(50) character set utf8
) engine=innodb default charset=utf8mb4;

create unique index uk_customer_cname on customer(cname);

insert into customer(cname, register_time, recommender) values('张三', Now(), '');
insert into customer(cname, recommender) values('李四', '张三'),('王五', '李四');

customer 是用户表,其中 cid 是主键;cname 上有一个唯一索引;recommender 是用户的推荐人。

实际查询涉及了很多表,经过简化之后存在性能问题的语句如下:

select c.*
from customer c
join customer r on (c.recommender = r.cname )
where r.cid = 1
and c.register_time between Now() - interval 1 day and Now();

大意是查找通过某人推荐,在指定时间段内注册用户

问题分析

了解问题之后,首先我让他给我发来了 explain 执行计划:

explain
select c.*
from customer c
join customer r on (c.recommender = r.cname )
where r.cname = '张三'
and c.register_time between Now() - interval 1 day and Now();

id|select_type|table|partitions|type |possible_keys    |key              |key_len|ref  |rows|filtered|Extra      |
--|-----------|-----|----------|-----|-----------------|-----------------|-------|-----|----|--------|-----------|
 1|SIMPLE     |r    |          |const|uk_customer_cname|uk_customer_cname|202    |const|   1|   100.0|Using index|
 1|SIMPLE     |c    |          |ALL  |                 |                 |       |     |   3|   33.33|Using where|

从结果可以看出,有一个全表扫描(type = ALL)的操作,显然这是因为 recommender 字段上缺少索引。

相关文章

MySQL 死锁 是指两个或多个事务互相等待对方持有的锁,从而导...
在MySQL中,InnoDB引擎通过Next-Key Locking技术来解决幻读问...
在数据库事务管理中,Undo Log 和 Redo Log 是两种关键日志,...
case when概述 sql语句中的case语句与高级语言中的switch语句...
其实很简单,只是为了忘记,做个记录,用的时候方便。 不管是...
1.进入服务,找到mysql服务,在属性里找到mysql的安装路径 2...