脚本宝典收集整理的这篇文章主要介绍了大批量数据删除语句的优化,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
有个离奇的场景,oracle数据库有两张千万级数据量的表A、B。A和B的对应关系为一对多,从A表中删除主键ID不在B表中的数据。
原删除语句
DELETE From A A WHERE A.ID NOT IN (
SELECT T.A_ID From B T WHERE T.FLAG = '1'
);
第一种
由于B表中的存储外键,所以有重复的情况,所以这里对not in里面的值的数据量进行去重,减少后约有63000多外键。
DELETE FROM A A WHERE A.ID NOT IN (
SELECT DISTINCT T.A_ID FROM B T WHERE T.FLAG = '1' AND T.A_ID IS NOT NULL
)
第二种
not in意味着每条数据都要进行6万多次的对比,这里使用not exists,每条数据进行一次子查询判断是否应该被删除。
DELETE FROM A A WHERE NOT EXISTS (
SELECT 1 FROM B T WHERE T.FLAG = '1' AND T.A_ID = A.ID
)
但是很可惜,B表中的外键上并没有索引(且外力不允许在这个表上建索引),这样从执行计划上看上面两种语句的效果是一样的。第一种每条数据多次循环判断,第二种每条数据多次IO读取。在测试删除的过程中都会卡死。。。。
对sql语句进行了再优化
既然没有索引可用,那就用视图吧缓存一下,想要精确定位到要删除的数据,所以将sql改为这样了
DELETE FROM A T WHERE T.ID = (
SELECT A.ID FROM A A
LEFT JOIN B B ON A.ID = B.A_ID AND B.FLAG = '1'
WHERE B.A_ID IS NULL AND A.ID = T.ID
)
更改后的sql,从执行计划上看已经有非常大的改观了。
可是实际跑起来就是无尽的等待。。。没法了给后面加上AND ROWNUM < 1000000
后,基本上两分钟内会删除结束,赶紧commIT。
直接上SQL:
CREATE TABLE A_BAK AS
SELECT A.* FROM A A JOIN B B ON A.ID = B.A_ID AND B.FLAG = '1'
这么多数据要删除,这么难搞,还是重新建表吧。这样A、B两个表只需要全表扫描一次,拿到所有不需要删除的数据放到一张新表中。
以上是脚本宝典为你收集整理的大批量数据删除语句的优化全部内容,希望文章能够帮你解决大批量数据删除语句的优化所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。