ORACLE解决大数据量导入排重

时间:2021-10-11 08:13:00

往百万数据量的数据库表插入几万条数据,如果不用排除重复,那简单的Insert语句就搞定了。但是要做到排重,并且还要把重复的数据记录下来,就值得思考一下了。

方法一:Insert + Select

         最简单的做法,再插入数据的时候,把每一条要插入数据与数据库表中每一条数据对比,发现重复就记录下不插入,不是则插入。

优点:方法简单,sql好写

缺点1.慢的要死,等待导入的功夫够你抽10袋烟的了。如果机器不灵光,或者数据库此时负载过高……别等了,过几个小时应该出结果。2.没有考虑要插入的数据本身有重复的情况。

虽然不推荐这种方法,但是对于小数据量的表(10w以下)也是可以接受的。另外也可以通过给数据对比的sql语句的条件上加索引,可以提高不少效率。

方法二:用Merge Into语句

Merge Into语句oracle9i新增的特性,

该语句的介绍:http://blog.csdn.net/EdgenHuang/article/details/3587912

该语句的本身目的是为了将InsertUpdate语句合并为一条语句所存在的,但是这里我们用到了它的特殊用法:确保唯一性约束

有些属性我们希望他在是唯一的,但是又不想将它作为唯一性约束,因为这样一旦一条数据违反约束,其他数据也就不能批量添加了。

如何用merge语句确保其唯一性约束?这篇文章写得很详细

http://www.idevelopment.info/data/Oracle/DBA_tips/SQL/SQL_14.shtml

该方法巧妙地运用了MERGEINTO的判断机制和dual表。例子3虽然用法正确,但是效率非常低下,还不如加了索引的方法一。而例子4则带来了效率上的极大提升,因为它比例子3少了一次查询。

优点:效率高,对于表中有200W数据,导入2W数据的情况,比加索引的方法一速度要快6倍(在我测试时,是4分钟与40秒)执行一条sql就可以排重。

缺点:不能够将因为重复未导入的记录展示出来。

用方法二虽然效率得到了很大提高,但是在需要将重复而为导入的记录展示时,就显得力不从心了。

有一个办法:利用MERGE INTOUPDATE分支,将重复的记录的某个字段更新(作为标识),全部记录导入后,用SELECT语句查出那些记录是重复的,最后将所更新的字段还原回去。先不说这个办法的复杂程度,但就对于效率来说,采用这个办法的效率也并不比方法一要高多少,而且容错性也不太好(考虑导入中途失败的情况)。

难道就只能又用土办法方法一了吗?方法二的运用虽然不是很成功,但是给我们提供了一个思路:用条件判断语句排重的插入一个表。所以我们还可以用PL/SQL

方法三:采用INSERT WHEN语句

该语句的介绍:http://psoug.org/reference/insert.html

在该语句的select分支中我们选择要排重的字段作为条件。当条件不符合(不重复)时插入到表中,条件符合(重复)时插入到一个临时表中,该表记录所有重复记录。当导入完成后,用SELECT语句查出那些记录是重复的。

优点:效率最高(同样是方法二中的情况,时间不到30秒)。

缺点:为了得到重复记录展示,要额外建立一张存重复记录的表。虽然如此,却比方法二要简单的多。