自己原文公众号: 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日到今天的数据和上次结果的数据进行一下比较。没多少的,几天的数据总比几年的数据快几百倍吧。
编辑推荐:
- 一次数据库的优化经历03-03
- database的connect03-03
- databas如何避免重复故障03-03
- database(Oracle MySQL)查询速度和数据量有关系吗?03-03
- OLTP的承载03-03
- Oracle跨主机复制数据库背后的意义03-03
- Oracle clone database03-03
- 系统进程是什么?怎么通过系统进程进行病毒分析?03-03
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
