PostgreSQL数据库数据去重
2019-03-11 本文已影响21人
zhglance
场景假设:
假设PostgreSQL数据库的表为students(student_id、student_name、age、gender)表,按照(student_id、student_name)进行去重,并删除重复的数据,使用PostgreSQL的ctid进行去重(类似于Oracle的rowId)。
方法一:
DELETE
FROM
students P
WHERE
P .ctid NOT IN (
SELECT
MAX (T .ctid)
FROM
students T
GROUP BY
T .student_id,
T .student_name
)
备注:方法简单,进适用于数据量很小的情况,不适用于数据量很大的情况,因为使用了in操作。亲测在50万数量级时,操作了40分钟没有执行完成。
方法二:
针对方法一使用IN的子查询范围太大导致性能比较差的问题,可以通过COUNT (ctid) > 1 缩小IN的范围。
DELETE
FROM
students M
WHERE
M .ctid IN (
SELECT
q.ctid
FROM
students q
INNER JOIN (
SELECT
T .student_id,
T .student_name,
MAX (T .ctid),
COUNT (T .ctid)
FROM
students T
GROUP BY
T .student_id,
T .student_name
HAVING
COUNT (T .ctid) > 1
) P ON q.student_id = P .student_id
AND q.student_name = P .student_name
AND P . MAX <> q.ctid
)
适合于数据量比较少,或者数据量比较大但是重复数据很少的情况,不适合数据量很大,而且数据重复很多的情况
方案三:
方案二虽然对IN做了优化,但是如果数据量很大,且重复的数据量很多的话性能就会比较差。方案三采用Exists代替IN。
DELETE
FROM
students q
WHERE
EXISTS (
SELECT
1
FROM
(
SELECT
T .student_id,
T .student_name,
MAX (T .ctid),
COUNT (T .ctid)
FROM
students T
GROUP BY
T .student_id,
T .student_name
HAVING
COUNT (T .ctid) > 1
) P
WHERE
q.student_id = P .student_id
AND q.student_name = P .student_name
AND P . MAX <> q.ctid
)