高效的28张表关联查询

书接上回

根据实际的业务需求

查询由
select * from A where data =‘28-FEB-2025’ and ID = 1 and dep_id = 11022;

几经转换后,变成了如下的查询:

select * from A where data =‘28-FEB-2025’ and ID = 1 and dep_id = 11022 and city_code||‘.’||int_code in (‘122.9’,‘13.11’,‘6.3’); (实际sql中in的条件为27个,我就不在这里赘述了)

这样的查询在实际的执行过程中,效果很差。

oracle并没有走我们在city_code与int_code上创建的索引。执行计划上,两个code拼接,是or。

当然这也并不难理解,虽然鲜少有人会在索引失效的原因里把拼接字符列在其中,但显然这种操作在我的理解下也是函数的一种。

现在这样,当然和我们实际的诉求相差较远。

我这个时候建议开发的同事把这一条拆开成若干条。

select * from A where data =‘28-FEB-2025’ and ID = 1 and dep_id = 11022 and city_code=:A and int_code = :B;

后两个条件在代码中使用绑定变量的方式,然后多线程一起跑。

开发的同事半天不语,沉默良久后表示,不现实。原因在于,这两个code在代码中是要根据前一个流程的计算得出的,每一次跑出来的结果数量并不总是相同的,并且在量级上相差较多,很难每次部署的时候都要去计算分配资源。

我询问开发的同事,两个code是在数据库中的查询得到的吗?

如果是,可以试着做join,在关联的column上建索引,也许会比现在少。

很可惜,并不是。

当时的气氛有些压抑,因为感觉月报上可以写,把查询时间降低了95%这样的傲人战绩了。结果现在只降了70%,和老板的诉求还是有差距的。

join?

你说,select 122 as city_code, 9 as int_code from dual; 算不算一种join?

我说,dual的确是一张表,但是没见人这么写过。

开发同事推了下眼睛,那我们今天就给他们开开眼!

于是,这条查询变成了:

select * from A where data =‘28-FEB-2025’ and ID = 1 and dep_id = 11022 and (city_code,int_code) in
(select 122 as city_code, 9 as int_code from dual union all
select 13 as city_code, 11 as int_code from dual union all
select 6 as city_code, 3 as int_code from dual
);
(实际sql中 union all的条件为27个,我就不在这里赘述了)

虽然很不美观,但是神奇的事情发生了,cost由300多降到了40.

索引,数据库承认了,nested loops也启动了,hash join也在,回来了,都回来了。

就这样一条简洁费时的sql,历经一周半,变成了一条冗长但高效的sql。执行计划的cost由最开始的接近两万,到现在的40。

虽然,这是一条28张“表”的union all,或许很多人看到他第一眼的瞬间就放弃了这个不美观,不合理的想法。但实际情况却超出了我们所有人的预期。

任何大胆的想法都去试试吧,世界会给你意想不到的回馈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值