如何有效地删除Postgresql 8.1表中的行?

Jin*_*Kim 6 sql database postgresql

我正在研究PostgreSQL 8.1 SQL脚本,它需要从表中删除大量行.

假设我需要删除的表是Employees(~260K行).它的主键名为id.

我需要从此表中删除的行存储在一个名为EmployeesToDelete(~10K记录)的单独临时表中,其中包含一个名为employee_id的Employees.id的外键引用.

有没有一种有效的方法来做到这一点?

起初,我想到了以下几点:

DELETE
FROM    Employees
WHERE   id IN
        (
        SELECT  employee_id
        FROM    EmployeesToDelete
        )
Run Code Online (Sandbox Code Playgroud)

但我听说使用"IN"子句和子查询可能效率低下,尤其是对于较大的表.

我查看了PostgreSQL 8.1文档,并提到了DELETE FROM ... USING但它没有示例,所以我不知道如何使用它.

我想知道以下是否有效并且效率更高?

DELETE
FROM    Employees
USING   Employees e
INNER JOIN
        EmployeesToDelete ed
ON      e.id = ed.employee_id
Run Code Online (Sandbox Code Playgroud)

非常感谢您的意见.

编辑:我运行了EXPLAIN ANALYZE,奇怪的是第一个DELETE跑得很快(几秒钟内),而第二个DELETE花了这么长时间(超过20分钟)我最终取消了它.

向临时表添加索引有助于提高性能.

这是对任何感兴趣的人的第一个DELETE的查询计划:

 Hash Join  (cost=184.64..7854.69 rows=256482 width=6) (actual time=54.089..660.788 rows=27295 loops=1)
   Hash Cond: ("outer".id = "inner".employee_id)
   ->  Seq Scan on Employees  (cost=0.00..3822.82 rows=256482 width=10) (actual time=15.218..351.978 rows=256482 loops=1)
   ->  Hash  (cost=184.14..184.14 rows=200 width=4) (actual time=38.807..38.807 rows=10731 loops=1)
         ->  HashAggregate  (cost=182.14..184.14 rows=200 width=4) (actual time=19.801..28.773 rows=10731 loops=1)
               ->  Seq Scan on EmployeesToDelete  (cost=0.00..155.31 rows=10731 width=4) (actual time=0.005..9.062 rows=10731 loops=1)

 Total runtime: 935.316 ms
(7 rows)
Run Code Online (Sandbox Code Playgroud)

在这一点上,我将坚持使用第一个DELETE,除非我能找到更好的编写方法.

bor*_*yer 10

不要猜测,衡量.尝试各种方法,看看哪个方法最短.另外,使用EXPLAIN来了解PostgreSQL将做什么,并看看你可以优化的地方.极少数PostgreSQL用户能够正确猜出最快的查询...


Qua*_*noi 7

我想知道以下是否有效并且效率更高?

    DELETE
    FROM    Employees e
    USING   EmployeesToDelete ed
    WHERE   id = ed.employee_id;
Run Code Online (Sandbox Code Playgroud)

这完全取决于您的索引选择性.

PostgreSQL往往采用MERGE IN JOININ谓词,它具有稳定的执行时间.

如果您已经有一个有序的结果集,它不受满足此条件的行数的影响.

有序的结果集需要排序操作或索引.与完全索引遍历PostgreSQL相比,完全索引遍历的效率非常低SEQ SCAN.

JOIN谓词,而另一方面,可以使用中获益NESTED LOOPS,如果你的指数是非常有选择性的,并且使用HASH JOIN的是它的inselective.

PostgreSQL 应该通过估计行数来选择正确的.

由于您有30k针对260K行的行,我希望HASH JOIN效率更高,您应该尝试在DELETE ... USING查询上构建计划.

为了确保,请发布两个查询的执行计划.