mysql明明有索引却用不到的情况
文章目录
- 一、前言
- 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明明有索引却用不到的情况相关推荐
- Mysql索引会失效的几种情况分析
转自:http://www.jb51.net/article/50649.htm 在做项目的过程中,难免会遇到明明给mysql建立了索引,可是查询还是很缓慢的情况出现,下面我们来具体分析下这种情况出现 ...
- cardinality mysql_Cardinality统计取值不准确导致MYSQL选错索引
场景简介 SQL明明可以走a索引,却走了慢的b索引? 场景模拟use muke; drop table if exists t13; CREATE TABLE `t13` ( `a` int(11) ...
- mysql中组合索引创建的原则是什么意思_面试前必须要掌握的MySQL索引最左前缀匹配原则...
在面试中,经常会遇到这种问题,如果我们设置联合索引的顺序是(a, b, c), 那么如果我们在查询时的顺序却是(a, c, b) 会走索引吗?这个问题被问到的频率之高,令人乍舌,在这篇文章中,我们就深 ...
- php普通索引和唯一索引,mysql下普通索引和唯一索引的效率对比
昨天有位同事说,他的网页查询过程中发现普通索引和唯一索引的效率是有差别的,普通索引比唯一索引快 今天在我的虚拟机中布置了环境,测试抓图如下: 抓的这几个都是第一次执行的,刷了几次后,取平均值,效率大致 ...
- MySQL第九章索引_MySQL高级(索引优化+慢查询定位)
一.先谈谈事务 1. ACID特性 1.1 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用: 1.2 一致性: 执行事务前后,数据库从一个一致性状态转换 ...
- mysql添加临时索引_mysql创建索引/删除索引操作
-- 1.ALTER 创建索引 -- table_name表名,column_list列名,index_name索引名 -- 创建index索引 ALTER TABLE table_name ADD ...
- mysql教程联合索引_MySQL中的联合索引学习教程
联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). 可以支持a | a,b| ...
- MySQL 如何创建索引?怎么优化?
2019独角兽企业重金招聘Python工程师标准>>> 索引类似大学图书馆建书目索引,可以提高数据检索的效率,降低数据库的IO成本.MySQL在300万条记录左右性能开始逐渐下降,虽 ...
- PHP面试MySQL数据库的索引
你好,是我琉忆,PHP程序员面试笔试系列图书的作者. 本周(2019.3.4至3.8)的一三五更新的文章如下: 周一:PHP面试MySQL数据库的基础知识 周三:PHP面试MySQL数据库的索引 周五 ...
最新文章
- 超级队长VR线下体验店落地上海,让娱乐突破想象
- 重大通知:社交系统ThinkSNS+ 发布公告!
- php多级遍历,php jquery实现无限级目录遍历展示代码
- 数据中异常值的鉴定和处理(1)
- php判断字符串里有英文,PHP针对中英文混合字符串长度判断及截取方法示例
- Mybatis 单独项目
- JXL读取,写入Excel
- Redis内存分析方法
- Layui表格点击详情
- 三角形个数(找规律)
- 马克·扎克伯格(Mark Zuckerberg)的第一幅作品成交价为30,201美元
- 装配uwsgi和nginx rabbitMQ
- 力扣刷题 DAY_83 贪心
- 5分钟python爬虫案例,手把手教爬取国内外最新疫情历史数据
- 香港特首到访阿里,她是来看几个年轻人的……
- 点云配准NDT+ICP
- Android kotlin工具类获取屏幕分辨率及宽高
- 【小家Spring】Spring AOP各个组件概述与总结【Pointcut、Advice、Advisor、Advised、TargetSource、AdvisorChainFactory...】
- Self-examination 自学考试 大学生自考 Students Self And Self Books 自考图书
- 【考研真题】四川大学2019初试真题 已更新在GitHub
热门文章
- java ajax jquery分页插件_分享精心挑选的12款优秀jQuery Ajax分页插件和教程
- 获得指定的配置文件中的数据
- torch转mnn笔记
- vs 设置 调试目录
- Can't connect to HTTPS URL because the SSL module is not available
- yolt 卫星图像进行快速目标识别的新方法
- pytorch | 深度学习分割网络U-net的pytorch模型实现
- Using AVStream.codec.time_base as a timebase hint to the muxer is deprecated
- python 多进程同步通信
- keras画acc和loss曲线图