使用的是PostgreSQL
在做大数据量(十万级)导入时,某些字段和数据库表里数据(千万级)重复的需要排除掉,把表数据查询出来用程序的方式判断去重效率很低,于是考虑用临时表。
因为不重复的数据我还要做一些其他的处理,所以查出来DataA,若不需做特殊处理可直接使用 insert into select
的方式将第2步的数据插入到原始表,然后清空临时表
第2步有两种方式,一种是用 not exists
的方式,如
SELECT
*
FROM
tableTemp t1
WHERE
NOT EXISTS ( SELECT 1 FROM tableName WHERE columnA = t1.columnA AND columnB = t1.columnB )
第二种方式是用 left join
SELECT
*
FROM
tableTemp t1
LEFT JOIN tableName t2 ON t2.columnA = t1.columnA AND t2.columnB = t2.columnB
WHERE
t2.columnA IS NULL
经测试(每个人的表结构和索引各有不同,我这里仅仅提供参考)
临时表数据量少时, not exists
用时较少,随着数据量越多用时越久。当数据达到10w时,用时25s。
临时表数据量少时,left join
用时30s,随着数据量越多变化不大,当数据达到10w时,用时40s。
结论1:单表去重时,只要导入的数据量不是特别特别大(20w级以上),优先使用 not exists 做去重。
但还有一种情况,就是需要对两个表做去重。
例如
SELECT
*
FROM
tableTemp t1
WHERE
NOT EXISTS (
SELECT 1 FROM tableNameA WHERE columnA = t1.columnA AND columnB = t1.columnB
union all
select 1 from tableNameB WHERE columnA = t1.columnA AND columnB = t1.columnB
);
SELECT
*
FROM
tableTemp t1
LEFT JOIN tableNameA t2 ON t2.columnA = t1.columnA AND t2.columnB = t1.columnB
LEFT JOIN tableNameB t3 ON t3.columnA = t1.columnA AND t3.columnB = t1.columnB
WHERE
t2.columnA IS NULL
AND t3.columnA IS NULL
这种情况下,
临时表数据少时,not exists
用时较少,随着数据量越多用时越久。当数据达到10w时,用时150s!!!。
临时表数据少时,left join
用时仍然是30s,随着数据量越多用时越久。当数据达到10w时,用时仍然是40s。
两者在数据量为3w时,用时不相上下
结论2:双表去重时,当导入的数据在3w以下时,用 not exists,在3w以上时,用 left join。