前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL隐式转换

MySQL隐式转换

作者头像
关忆北.
发布2023-10-11 09:35:20
1770
发布2023-10-11 09:35:20
举报
文章被收录于专栏:关忆北.
隐式转换概念

When an operator is used with operands of different types, type conversion occurs to make the operands compatible. Some conversions occur implicitly.

当运算符与不同类型的操作数一起使用时,将进行类型转换以使操作数兼容。某些转换是隐式发生的。 官方给的定义些许抽象,下面看例子。 有车辆表vehicle。

代码语言:javascript
复制
create table vehicle
(
    id           varchar(32) not null
        primary key,
    brand        varchar(10) not null comment '车辆品牌',
    plate_number varchar(10) not null comment '车牌号'
)
    comment '车辆信息表';

INSERT INTO `daily_test`.`vehicle` (`id`, `brand`, `plate_number`) VALUES ('1', '比亚迪-汉DMI', '鲁B.11111');
INSERT INTO `daily_test`.`vehicle` (`id`, `brand`, `plate_number`) VALUES ('2', '比亚迪-秦DMI', '鲁B.22222');
INSERT INTO `daily_test`.`vehicle` (`id`, `brand`, `plate_number`) VALUES ('3', '比亚迪-宋DMI', '鲁B.33333');

查询语句:

代码语言:javascript
复制
select id, brand from vehicle where id = 1;

使用explain查询执行计划,扫描行数是3,即全表数据。

在这里插入图片描述
在这里插入图片描述

若将查询语句改为:

代码语言:javascript
复制
select id, brand from vehicle where id = '1';

使用explain查询执行计划,扫描行数是1,即使用了主键索引。

为什么两者逻辑一致执行存在差异

由于表数据量较少,共3行,所以两者在执行时间上相差无几,但是在数据量较大的表中,扫全表和使用主键索引的性能差距还是相距甚远的。 vehicle表中id字段被定义为varchar类型,但是在第一个查询语句中,where条件中1为int类型,那么,在执行SQL时便相当于:

代码语言:javascript
复制
select id, brand from vehicle where CAST(id AS signed int) = 1;

即在你不知道的情况下,MySQL “私自” 使用了CAST()函数,大家都知道, 对于索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。(无法通过树搜索功能快速定位)。

出现隐式转换的场景

翻译自MySQL

  • 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换
  • 两个参数都是字符串,会按照字符串来比较,不做类型转换
  • 两个参数都是整数,按照整数来比较,不做类型转换
  • 十六进制的值和非数字做比较时,会被当做二进制串
  • 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp
  • 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
  • 所有其他情况下,两个参数都会被转换为浮点数再进行比较
隐式字符编码转换

当两个表的字符集不同时,关联查询时会导致被驱动表无法命中索引。

代码语言:javascript
复制
mysql> CREATE TABLE `tradelog` (
  `id` int(11) NOT NULL,
  `tradeid` varchar(32) DEFAULT NULL,
  `operator` int(11) DEFAULT NULL,
  # 存储格式:yyyy-MM-dd
  `t_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `tradeid` (`tradeid`),
  KEY `t_modified` (`t_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
代码语言:javascript
复制
CREATE TABLE `trade_detail` (
  `id` int(11) NOT NULL,
  `tradeid` varchar(32) DEFAULT NULL,
  `trade_step` int(11) DEFAULT NULL, /*操作步骤*/
  `step_info` varchar(32) DEFAULT NULL, /*步骤信息*/
  PRIMARY KEY (`id`),
  KEY `tradeid` (`tradeid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into tradelog values(1, 'aaaaaaaa', 1000, now());
insert into tradelog values(2, 'aaaaaaab', 1000, now());
insert into tradelog values(3, 'aaaaaaac', 1000, now());

insert into trade_detail values(1, 'aaaaaaaa', 1, 'add');
insert into trade_detail values(2, 'aaaaaaaa', 2, 'update');
insert into trade_detail values(3, 'aaaaaaaa', 3, 'commit');
insert into trade_detail values(4, 'aaaaaaab', 1, 'add');
insert into trade_detail values(5, 'aaaaaaab', 2, 'update');
insert into trade_detail values(6, 'aaaaaaab', 3, 'update again');
insert into trade_detail values(7, 'aaaaaaab', 4, 'commit');
insert into trade_detail values(8, 'aaaaaaac', 1, 'add');
insert into trade_detail values(9, 'aaaaaaac', 2, 'update');
insert into trade_detail values(10, 'aaaaaaac', 3, 'update again');
insert into trade_detail values(11, 'aaaaaaac', 4, 'commit');

执行语句:

代码语言:javascript
复制
select d.* from tradelog l, trade_detail d where d.tradeid=l.tradeid and l.id=2; 

编码格式不同时,上述查询语句就变成了:

代码语言:javascript
复制
select * from trade_detail  where CONVERT(traideid USING utf8mb4)=$L2.tradeid.value; 

CONVERT() 函数,在这里的意思是把输入的字符串转成 utf8mb4 字符集。

要在编写SQL语句时养成使用explain的习惯,及时发现SQL潜在问题,避免慢SQL导致的性能问题。

最后,祝大家2023新年快乐。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 隐式转换概念
  • 为什么两者逻辑一致执行存在差异
  • 出现隐式转换的场景
  • 隐式字符编码转换
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档