阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

耗时数小时,‘Not in’ SQL 优化

75次阅读
没有评论

共计 2071 个字符,预计需要花费 6 分钟才能阅读完成。

导读 在 DBA 所优化的数据库环境中,绝大多数性能问题其实是由于 SQL 编写不当导致的。SQL 的世界无奇不有,今天我们一起见识一条让你绝对想吐血的杀手 SQL。

某保险客户,ETL 耗时数个小时,我们做了 sql report 发现压力主要在其中一个 SQL 上。

耗时数小时,‘Not in’SQL 优化

单次执行时间:5788(秒)

单次逻辑读:10 亿 (块)

单次返回行数:21 万 (行)

我们首先看 SQL 语句,因为比较长,此处只节选部分的

耗时数小时,‘Not in’SQL 优化

查看其执行计划:

耗时数小时,‘Not in’SQL 优化

我们主要关注一下从 7 到 16 行:发现存在两次全表扫描。中间做了一次 filter。

多年的经验告诉我,两个全表扫组成的 Filter,问题很严重, 因为涉及数据逐条处理。而这个执行计划里,被驱动表还是全表扫。

Not In/In 操作有时候的确会产生 Filter 操作,在 11g 之前的版本,要把 not in 语句转换成反连接,not in 条件的列必须有 Not null 属性, 或者语句中带入了 not null 的限制,否则只能采用 Filter,逐条过滤.

我们举例说明一下:

SQL1:CREATE TABLE T_OBJ AS SELECT OBJECT_ID,OWNER,OBJECT_NAME,OBJECT_TYPE FROM DBA_OBJECTS WHERE OWNER !=‘SEROL’;SQL2:CREATE TABLET_TABLE AS SELECT OWNER,TABLE_NAME FROM DBA_TABLES WHERE OWNER!=’SEROL’;

查看 T_OBJ 的属性:

耗时数小时,‘Not in’SQL 优化

发现有在三列上都没有 not null 的限制。

我们此时伪装成 10G 的优化器。

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

执行以下 SQL:

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

此时查看执行计划,我们发现走的是 filter:

耗时数小时,‘Not in’SQL 优化

但在 11g 版本中,优化器可以自动把 Not in 操作从昂贵的 Filter 转换成 Null-Aware-Anti-Join。

若加个 Not null 条件或者栏位属性设为 not null

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

再次执行相同语句:

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

再次查看执行计划:

耗时数小时,‘Not in’SQL 优化

此时我们发现,在执行计划中,走了 hash join anti.

并且,在 11g 里面,允许 not in 列没有 not null 限制也可以转换 Anti-Join.

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

查看执行计划:

耗时数小时,‘Not in’SQL 优化

我们看到,此时在没有非空限制的情况下,也走了 hash join anti.

这个特性, 可通过优化器参数控制。

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

再次执行以上语句并查看执行计划:

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

耗时数小时,‘Not in’SQL 优化

发现仍然走的是 hash join anti.

经过验证,不是这个参数设置问题

Not in 的逻辑,就是结果集之间的互斥,其实有多种改写的方式,比如:

— Not exists

— Outer Join + is null

— Minus

not in 与以上三种写法的区别是:not in 是会排斥空值。

我们尝试改写。

耗时数小时,‘Not in’SQL 优化

接下来正当你以为会发生奇迹的时候,语句报错了!

耗时数小时,‘Not in’SQL 优化

为什么会报错呢?

如果我们把该语句转换为 not in 的方式:

耗时数小时,‘Not in’SQL 优化

根据 not in 的逻辑,此时在 fee_code 前应该加上’A.’,当然这也是没有问题的,但是,再次看这条语句就会变成:

耗时数小时,‘Not in’SQL 优化

由于 TMP_APP_xxx_PREM A 中并没有 FEE_CODE 字段, 所以,Not in 无法自动改成 Null Aware ANTI JOIN。

所以,至此答案揭晓,竟然是写错了?!我猜中了这开头,却没有猜中这结局。

但在本案例中,由于 SQL 语句中没有显式写出表明,导致在前期分析过程中一直没有发现这个错误。

你是不是也很无语,其实我更想问的是,你是不是也经常写出杀手 SQL 呢,但没关系,你有病我有药啊。(无辜脸,不要打我)

我们都知道,在 DBA 所优化的数据库环境中,绝大多数性能问题其实是由于 SQL 编写不当导致的。

对于未上线系统,通过前期的 SQL 审核管控,将 80% 的 SQL 问题消灭在萌生阶段,对于线上运行系统,发现和解决潜在的性能问题,可做到提前预防,防患于未然。

SQL 审核,让 DBA 由系统的急救医生转身成为系统的保健医生

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

原文来自微信公众号:数据和云

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-24发表,共计2071字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中