一次数据库的优化经历

来源:这里教程网 时间:2026-03-03 17:20:39 作者:

自己原文公众号: https://mp.weixin.qq.com/s/H5IEqcasnN4nCoipUauH1w

前几天有个学员问我个SQL能不能优化。SQL如下:

SELECT S.CARD_NO  FROM  S  

WHERE S.DATE BETWEEN TO_DATE('20171002 00:00:00', 'yyyymmdd hh24:mi:ss') AND TO_DATE('20180701 23:59:59', 'yyyymmdd hh24:mi:ss')  

AND S.CARD_NO NOT IN  

   ( 

   SELECT P.CARD_NO  FROM  P  

   WHERE  P.DATE between to_date('20171002 00:00:00', 'yyyymmdd hh24:mi:ss')  and to_date('20210627 23:59:59', 'yyyymmdd hh24:mi:ss')

   )  

AND S.CARD_NO NOT IN  

   ( 

   SELECT s.CARD_NO  FROM s   

  AND s.DATE between to_date('20171002 00:00:00', 'yyyymmdd hh24:mi:ss')  and to_date('20210627 23:59:59', 'yyyymmdd hh24:mi:ss')

   )  

背景是

第一段的时间为2017年10月02日,到2018年07月01日。这个SQL要查询的,就是这段时间内购买了的、并且截至2021年06月27日尚未兑换或退换的票券信息。

 

第二段时间是从2017年10月2日,到2021年6月27日。排除这段时间内P表(兑换记录表)中的数据;card_no not in,也就是把购买了并且已兑换的票券排除掉。

 

第三段时间是从2017年10月2日,到2021年6月27日。排除这段时间内S表(购买、退换货记录表)中的数据;card_no not in,就是把购买了但进行了退换的票券排除。

 

现在执行了3天半了,期望6小时。这个sql手动执行,晚上12点左右执行;2到3个月执行一次。

当我看到这个震惊了,虽然不是我见过最长的,但是执行3天半这个还是有点狠的。

 

    我第一感觉是要查有效期以外有多少没兑换的要做失效处理。如果是我,我考虑这种有个有效期。一问说长期有效。其实这是不合理的。

    

S表 购买、退货记录 大约4亿条数据,从2014年至今。而条件是要查S表一年的数据。符合条件的大约1000万。(不科学)

P表  兑换记录 大约9千万条数据,符合条件的大约7000万。

然后就是1000万的看看不在7000万中的有多少,然后再看看再排除自己范围中“ 退换”的数据。退是在S表,兑换是在P表。有点抓狂,有点反人类。

在经历了差集改写也无效的情况下,总觉得这样去返回几百万总归是不快的。

    这个时候发挥一个无敌的想法,改实现方式。经过了解上次他们是执行过的。这就是为什么结束时间都是2021年6月27日。那么也就是说如果开始时间都是2017年10月2日,结束时间都是2021年6月27日(SQL上是这么写的),那么7月10日以后运行从逻辑上来说,结果是一样的。也就是说无需运行就用上次的结果就行。从逻辑上推断上次的结果一定是导出下载了,不可能查完算了。

     那么不用执行就是最高境界,英雄中有句话,剑的三个境界。 第一层境界:手中有剑心中有剑第二层境界:手中无剑心中有剑第三层境界:手中无剑心中也无剑,那就是和平。优化的最高境界就是不做。

     题外话如果说时间改变了呢?也好办。上次计算的结果落在表中,那么这次只要看看2021年6月27日到今天的数据和上次结果的数据进行一下比较。没多少的,几天的数据总比几年的数据快几百倍吧。

相关推荐