文章目录

  • 一、前言
    • 1、问题sql:
    • 2、explain一下
    • 3、量级
  • 二、排查过程
    • 1、难道是字段类型的问题,表结构如下
    • 2、查看字段编码
    • 3、修改编码一致看看
      • (1)解释:
      • (2)查看效果
    • 4、为何会出现这种原因
      • (1)查看数据库编码
      • (2)解决方案
  • 三、最后

一、前言

如题所示,博主这边在两表关键更新的时候,明明关联字段都有索引,但是竟然没用上?百思不得其解,最后发现原来是编码格式的问题,此处记录一下。

1、问题sql:

update test_a as a  left join test_b as b on a.uuid=b.uuid  set a.log_time = b.log_time;

2、explain一下

mysql> explain update test_a as a  left join test_b as b on a.uuid=b.uuid  set a.log_time = b.log_time;
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+
|  1 | UPDATE      | a     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |        1 |   100.00 | NULL        |
|  1 | SIMPLE      | b     | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 36873167 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+----------+----------+-------------+

可以看到这里扫描b表3600W条数据,导致这条sql十分缓慢,我滴天,不能忍的。

3、量级

a表:10W级别
b表:3600W级别

二、排查过程

1、难道是字段类型的问题,表结构如下

CREATE TEMPORARY TABLE if not exists test_a (uuid varchar(32) NOT NULL PRIMARY KEY,`log_time` datetime NOT NULL ,`daily_nums` VARCHAR(100) NOT NULL DEFAULT '0',UNIQUE KEY `uuid` (`uuid`)) ;CREATE TABLE `test_b` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`uuid` varchar(32) NOT NULL DEFAULT '',PRIMARY KEY (`id`),UNIQUE KEY `uuid` (`uuid`),
) ENGINE=InnoDB  DEFAULT CHARSET=utf8

这里可以看到,两个表的关联字段都是有索引的,类似都是varchar类型

2、查看字段编码

这是在百度的时候发现的,有人提出字段编码的问题,博主一想还真是有可能,不查不知道,一查吓一跳。参考:

https://www.hxstrive.com/article/829.htm

show full columns from test_b;   +-------------------+--------------+-----------------+------+-----+---------+----------------+------------+-------------+
| Field             | Type         | Collation       | Null | Key | Default | Extra          | Privileges | Comment     |
+-------------------+--------------+-----------------+------+-----+---------+----------------+------------+-------------+
| id                | bigint(20)   | NULL            | NO   | PRI | NULL    | auto_increment | select     |             |
| uuid              | varchar(32)  | utf8_general_ci | NO   | UNI |         |                | select     |             |show full columns from test_a;
+--------------------+-------------+--------------------+------+-----+---------+-------+------------+---------+
| Field              | Type        | Collation          | Null | Key | Default | Extra | Privileges | Comment |
+--------------------+-------------+--------------------+------+-----+---------+-------+------------+---------+
| uuid               | varchar(32) | utf8mb4_general_ci | NO   | PRI | NULL    |       | select     |         |
| user_id            | bigint(20)  | NULL               | NO   |     | NULL    |       | select     |         |

通过对比我们可以发现,两个表的uuid字段编码是不一样的,一个是普通的utf8类型,一个是utf8mb4 类型,难道确实是编码的原因吗?

3、修改编码一致看看

博主这里是临时表,所以只需要在建表的时候指定一下即可。

CREATE TEMPORARY TABLE if not exists test_a (uuid varchar(32) NOT NULL PRIMARY KEY,`log_time` datetime NOT NULL ,`daily_nums` VARCHAR(100) NOT NULL DEFAULT '0',UNIQUE KEY `uuid` (`uuid`)) DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

(1)解释:

1)DEFAULT CHARACTER SET utf8:数据库字符集。设置数据库的默认编码为utf8,这里utf8中间不要"-";2)COLLATE utf8_general_ci:数据库校对规则。

(2)查看效果

mysql> explain update test_a as a,test_b as b set a.log_time = b.log_time where a.uuid=b.uuid;
+----+-------------+-------+------------+--------+----------------------------+------+---------+-------------------+------+----------+-------+
| id | select_type | table | partitions | type   | possible_keys              | key  | key_len | ref               | rows | filtered | Extra |
+----+-------------+-------+------------+--------+----------------------------+------+---------+-------------------+------+----------+-------+
|  1 | UPDATE      | a     | NULL       | ALL    | PRIMARY,uuid,uuid_2,uuid_3 | NULL | NULL    | NULL              |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | b     | NULL       | eq_ref | uuid                       | uuid | 98      | analyze_em.a.uuid |    1 |   100.00 | NULL  |

这里可以看到,确实是用到索引了,经过博主测试,用到索引之后,此sql只需要1-2s左右就跑完了,性能提升将近百倍。

4、为何会出现这种原因

(1)查看数据库编码

mysql> show variables like '%char%';
+--------------------------+-----------------------------------------------+
| Variable_name            | Value                                         |
+--------------------------+-----------------------------------------------+
| character_set_client     | gbk                                           |
| character_set_connection | gbk                                           |
| character_set_database   | utf8mb4                                      |
| character_set_filesystem | binary                                        |
| character_set_results    | gbk                                           |
| character_set_server     | utf8                                          |
| character_set_system     | utf8                                          |
| character_sets_dir       | xxx\charsets\ |
+--------------------------+-----------------------------------------------+

注意这里的character_set_database ,它的含义是我们创建表的时候,默认会使用此种编码格式。而我们创建临时表的时候,大多数情况下是不主动设置编码格式的,因此就会默认使用utf8mb4 格式。 但是呢,我们创建普通表的时候,又习惯于设置utf8类型,所以就导致了这种问题的出现。

(2)解决方案

1)创建表的时候,指定好编码格式
2)设置表的默认编码格式,重启数据库

三、最后

不得不说已经好久没写博客了,一方面是值得写的内容不多,一方面也是忙吧。还是希望能坚持写博客的习惯,奥利给!

end

mysql明明有索引却用不到的情况相关推荐

  1. Mysql索引会失效的几种情况分析

    转自:http://www.jb51.net/article/50649.htm 在做项目的过程中,难免会遇到明明给mysql建立了索引,可是查询还是很缓慢的情况出现,下面我们来具体分析下这种情况出现 ...

  2. cardinality mysql_Cardinality统计取值不准确导致MYSQL选错索引

    场景简介 SQL明明可以走a索引,却走了慢的b索引? 场景模拟use muke; drop table if exists t13; CREATE TABLE `t13` ( `a` int(11) ...

  3. mysql中组合索引创建的原则是什么意思_面试前必须要掌握的MySQL索引最左前缀匹配原则...

    在面试中,经常会遇到这种问题,如果我们设置联合索引的顺序是(a, b, c), 那么如果我们在查询时的顺序却是(a, c, b) 会走索引吗?这个问题被问到的频率之高,令人乍舌,在这篇文章中,我们就深 ...

  4. php普通索引和唯一索引,mysql下普通索引和唯一索引的效率对比

    昨天有位同事说,他的网页查询过程中发现普通索引和唯一索引的效率是有差别的,普通索引比唯一索引快 今天在我的虚拟机中布置了环境,测试抓图如下: 抓的这几个都是第一次执行的,刷了几次后,取平均值,效率大致 ...

  5. MySQL第九章索引_MySQL高级(索引优化+慢查询定位)

    一.先谈谈事务 1. ACID特性 1.1 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用: 1.2 一致性: 执行事务前后,数据库从一个一致性状态转换 ...

  6. mysql添加临时索引_mysql创建索引/删除索引操作

    -- 1.ALTER 创建索引 -- table_name表名,column_list列名,index_name索引名 -- 创建index索引 ALTER TABLE table_name ADD ...

  7. mysql教程联合索引_MySQL中的联合索引学习教程

    联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). 可以支持a | a,b| ...

  8. MySQL 如何创建索引?怎么优化?

    2019独角兽企业重金招聘Python工程师标准>>> 索引类似大学图书馆建书目索引,可以提高数据检索的效率,降低数据库的IO成本.MySQL在300万条记录左右性能开始逐渐下降,虽 ...

  9. PHP面试MySQL数据库的索引

    你好,是我琉忆,PHP程序员面试笔试系列图书的作者. 本周(2019.3.4至3.8)的一三五更新的文章如下: 周一:PHP面试MySQL数据库的基础知识 周三:PHP面试MySQL数据库的索引 周五 ...

最新文章

  1. 超级队长VR线下体验店落地上海,让娱乐突破想象
  2. 重大通知:社交系统ThinkSNS+ 发布公告!
  3. php多级遍历,php jquery实现无限级目录遍历展示代码
  4. 数据中异常值的鉴定和处理(1)
  5. php判断字符串里有英文,PHP针对中英文混合字符串长度判断及截取方法示例
  6. Mybatis 单独项目
  7. JXL读取,写入Excel
  8. Redis内存分析方法
  9. Layui表格点击详情
  10. 三角形个数(找规律)
  11. 马克·扎克伯格(Mark Zuckerberg)的第一幅作品成交价为30,201美元
  12. 装配uwsgi和nginx rabbitMQ
  13. 力扣刷题 DAY_83 贪心
  14. 5分钟python爬虫案例,手把手教爬取国内外最新疫情历史数据
  15. 香港特首到访阿里,她是来看几个年轻人的……
  16. 点云配准NDT+ICP
  17. Android kotlin工具类获取屏幕分辨率及宽高
  18. 【小家Spring】Spring AOP各个组件概述与总结【Pointcut、Advice、Advisor、Advised、TargetSource、AdvisorChainFactory...】
  19. Self-examination 自学考试 大学生自考 Students Self And Self Books 自考图书
  20. 【考研真题】四川大学2019初试真题 已更新在GitHub

热门文章

  1. java ajax jquery分页插件_分享精心挑选的12款优秀jQuery Ajax分页插件和教程
  2. 获得指定的配置文件中的数据
  3. torch转mnn笔记
  4. vs 设置 调试目录
  5. Can't connect to HTTPS URL because the SSL module is not available
  6. yolt 卫星图像进行快速目标识别的新方法
  7. pytorch | 深度学习分割网络U-net的pytorch模型实现
  8. Using AVStream.codec.time_base as a timebase hint to the muxer is deprecated
  9. python 多进程同步通信
  10. keras画acc和loss曲线图