相关文章推荐
阳刚的骆驼  ·  可检测的查询性能瓶颈类型 - Azure ...·  昨天    · 
忧郁的大象  ·  探索Datagrip:数据库管理的艺术 - ·  3 小时前    · 
朝气蓬勃的火腿肠  ·  保罗中国行想念妻女CP4 ...·  6 月前    · 
鬼畜的领结  ·  地铁上新5号线直通黄家湖大学城- ...·  9 月前    · 
大方的柑橘  ·  徐少华出席省政协参事、文史馆员联组讨论会 ...·  12 月前    · 
暗恋学妹的消防车  ·  张怡宁到底有多强?83个月第一因找不到对手退 ...·  1 年前    · 
慷慨大方的绿茶  ·  QS2022丹麦大学排名一览表– 留学网-南华中天·  1 年前    · 
Code  ›  18 | 为啥SQL逻辑相同,性能差异大开发者社区
索引 select sql优化
https://cloud.tencent.com/developer/article/1767557
愉快的钱包
1 年前
作者头像
HaC
0 篇文章

18 | 为啥SQL逻辑相同,性能差异大

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > HaC的技术专栏 > 18 | 为啥SQL逻辑相同,性能差异大

18 | 为啥SQL逻辑相同,性能差异大

作者头像
HaC
发布 于 2020-12-30 17:48:06
545 0
发布 于 2020-12-30 17:48:06
举报

第一种:隐式类型转换

  1. 如果规则是“将字符串转成数字”,那么就是做数字比较,结果应该是 1;
  2. 如果规则是“将数字转成字符串”,那么就是做字符串比较,结果应该是 0。

情况一:

此时cg_bidid的类型是bigint 在 MySQL 中,字符串和数字做比较的话,是将字符串转换成数字。

EXPLAIN SELECT * FROM cg_bid WHERE id ="104";
EXPLAIN SELECT * FROM cg_bid WHERE id =104;

这两句都一样的性能,所以说where的值是整型,右侧的值无论是字符串还是整型,不会出现隐式类型转换。

情况二:

此时cg_bid的id 的类型为varchar

where条件的值是字符串类型,右侧的值是整型,会进行类型转换,会进行全盘扫描,无法使用索引。

EXPLAIN SELECT * FROM cg_bid WHERE id =104;

explain结果:

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

看到这里全盘扫描了(rows),而且key为NULL,证明没有走索引。

第一种:条件字段函数操作

CREATE TABLE `tradelog` (
  `id` int(11) NOT NULL,
  `tradeid` varchar(32) DEFAULT NULL,
  `operator` int(11) DEFAULT NULL,
  `t_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `tradeid` (`tradeid`),
  KEY `t_modified` (`t_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

这种不会走索引

select count(*) from tradelog where month(t_modified)=7;

下面是这个 t_modified 索引的示意图。方框上面的数字就是 month() 函数对应的值。

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

果你的 SQL 语句条件用的是 where t_modified='2018-7-1’的话,引擎就会按照上面绿色箭头的路线,快速定位到 t_modified='2018-7-1’需要的结果。 为了能够用上索引的快速定位能力,我们就要把 SQL 语句改成基于字段本身的范围查询。按照下面这个写法,优化器就能按照我们预期的,用上 t_modified 索引的快速定位能力了。

select count(*) from tradelog 
where (t_modified >= '2016-7-1' 
and t_modified<'2016-8-1') 
or  (t_modified >= '2017-7-1' 
and t_modified<'2017-8-1') 
or  (t_modified >= '2018-7-1' and t_modified<'2018-8-1');

不过优化器在个问题上确实有“偷懒”行为,即使是对于不改变有序性的函数,也不会考虑使用索引。比如,对于 select * from tradelog where id + 1 = 10000 这个 SQL 语句,这个加 1 操作并不会改变有序性,但是 MySQL 优化器还是不能用 id 索引快速定位到 9999 这一行。所以,需要你在写 SQL 语句的时候,手动改写成 where id = 10000 -1 才可以。

第三种:隐式字符编码转换

连表,字符集不一样也会不走索引。

像这种:

select * from trade_detail  
where CONVERT(traideid USING utf8mb4)=$L2.tradeid.value; 

CONVERT() 函数,在这里的意思是把输入的字符串转成 utf8mb4 字符集。 连接过程中要求在被驱动表的索引字段上加函数操作,是直接导致对被驱动表做全表扫描的原因。

假如表的数据较大,这种情况可以使用以下的方法优化:移到右侧

select operator from tradelog  
where traideid = CONVERT($R4.tradeid.value USING utf8mb4); 

课程后面看到有一个有意思的问答:

老师,有道面试题困扰了很久,求指教!题目是这样的,a表有100条记录,b表有10000条记录,两张表做关联查询时,是将a表放前面效率高,还是b表放前面效率高?网上各种答案,但感觉都没有十分的说服力,期待老师的指点!

 
推荐文章
阳刚的骆驼  ·  可检测的查询性能瓶颈类型 - Azure SQL Database | Microsoft Learn
昨天
忧郁的大象  ·  探索Datagrip:数据库管理的艺术 -
3 小时前
朝气蓬勃的火腿肠  ·  保罗中国行想念妻女CP4 发家人合影表思家心切-搜狐体育!!!
6 月前
鬼畜的领结  ·  地铁上新5号线直通黄家湖大学城- 武汉市人民政府门户网站
9 月前
大方的柑橘  ·  徐少华出席省政协参事、文史馆员联组讨论会 广东省人民政府门户网站
12 月前
暗恋学妹的消防车  ·  张怡宁到底有多强?83个月第一因找不到对手退役_手机新浪网
1 年前
慷慨大方的绿茶  ·  QS2022丹麦大学排名一览表– 留学网-南华中天
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号