前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >74-这类SQL优化,oracle输给了mysql,如何补救?

74-这类SQL优化,oracle输给了mysql,如何补救?

作者头像
老虎刘
发布2022-06-22 18:22:53
3164
发布2022-06-22 18:22:53
举报
文章被收录于专栏:老虎刘谈oracle性能优化

MySQL和Oracle都是Oracle公司旗下的关系型数据库,在最近几年全球关系型数据库使用排行榜上,一直占据头两把交椅(下图是2020年2月的一个排名)。

oracle数据库是Oracle公司主打产品,是一款接近于完美的数据库产品,当然其使用授权费用也是比较昂贵的;Mysql虽然没有oracle那么强大,但是因为其开源免费的优点,被广泛使用。

我主要以研究Oracle数据库(尤其是性能方面)为主,也会关注一些Mysql的技术,今天列举的一个案例,就是Mysql优化器比它的“老大哥”oracle做的还要好的一个例子。

首先说一个区别,mysql的索引保存null值,而oracle不保存全是null值的索引记录,比如下面的查询:

select * from t1 where object_id is null;

这样的sql,在object_id 定义可为null,而且存在单字段索引的时候,mysql是可以使用索引的,但oracle不可以,需要创建(object_id,0)这样的联合索引,上面sql才能使用索引。在oracle中,如果要使用索引,上面的写法是不建议的,索引列应尽量定义为not null。

我们今天要比较的sql如下:

select owner,max(object_id) as max_object_id from tbig group by owner;

业务逻辑:选出每个owner对应的最大(最小也是一样)的object_id,已知owner的唯一值比较少。

Mysql:

mysql的优化器有一个loose index scan的技术,类似oracle 的index skip scan,可以高效的执行上面sql,官方文档相关链接:

https://dev.mysql.com/doc/refman/8.0/en/group-by-optimization.html

在8.0 版本,mysql增加了一个非常好用的新特性,可以使用explain anzlyze来查看执行计划和cost。这个特性类似oracle的 gather_plan_statistics + dbms_xplan.display_cursor( format=>'all stats,last')。

表结构及索引情况:

CREATE TABLE tbig (

id smallint(5) unsigned NOT NULL ,

owner varchar(30) null,

object_id int(10) unsigned NULL,

create_date datetime NULL,

PRIMARY KEY (id),

KEY idx_tbig_owner_object_id (owner,object_id)

) ;

插入一下数据,省略。

explain analyze select owner,max(object_id) as max_object_id from tbig group by owner;

执行计划:

因为owner和object_id两个字段定义都是null,这里是没有使用loose index scan。

将其中任意一个字段定义改成not null:

alter table tbig modify owner varchar(30) not null;

再看看执行计划:

explain analyze select owner,max(object_id) as max_object_id from tbig group by owner;

这个时候执行计划使用的就是高效的loose index scan(cost 比上面低很多),关键字为index_for_group_by

疑问:如果这时候把owner字段定义再改回null,alter table tbig modify owner varchar(30) null; 还是会使用loose index scan的执行计划,我对Mysql的这个特性有点不太理解,如有mysql专家可以帮忙解惑,万分感谢。

Oracle:

oracle虽然很早的版本就有了index skip scan技术,但是却无法实现与mysql 的loose index scan 相同的优化。

相同的表结构,创建 owner + object_id 联合索引,如果两个字段定义为可为null,上面sql使用的是全表扫描的执行计划:

如果owner和object_id两个字段其中任意一个定义为not null,那么上面sql可以使用index fast full scan的执行计划。或者我们在sql中加入一个where owner is not null 的条件,也可以达到相同目的。这种情况虽然性能有一定的提升,但也只是利用了索引比表小的原理,没有很多的改善:

不用where owner is not null,使用下面命令也会得到相同执行计划:

alter table tbig modify owner not null;

补救方法:

这种情况,如果我们设计的关系模型是符合范式规范的,那么应该还有一张表是用来只保存owner信息的,根据owner唯一值少的先决条件,这个表一定是一个小表(比如叫t_user),这时,我们可以用标量子查询的写法,来优化这个sql(注:在owner对应的object_id有空值的时候,两个sql在逻辑上不完全等价),标量子查询在这里起到了积极意义(题外话:很多事情都不是非黑即白,都有适用的场景,标量子查询也有其正面的意义):

select * from

(

select username as owner,(select max(object_id) from tbig s where s.owner=m.username) as max_object_id

from t_user m

) where max_object_id is not null;

经过上面的改写,sql执行效率会有大幅提升(tbig表越大,效率提升越明显),与mysql的loose index scan的实现效果相差无几了。有兴趣的朋友可以自己动手测试一下。

总结:

没有。

春天来了,疫情也早点去吧。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老虎刘谈oracle性能优化 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档