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,除非我能找到更好的编写方法.
我想知道以下是否有效并且效率更高?
DELETE
FROM Employees e
USING EmployeesToDelete ed
WHERE id = ed.employee_id;
Run Code Online (Sandbox Code Playgroud)
这完全取决于您的索引选择性.
PostgreSQL往往采用MERGE IN JOIN的IN谓词,它具有稳定的执行时间.
如果您已经有一个有序的结果集,它不受满足此条件的行数的影响.
有序的结果集需要排序操作或索引.与完全索引遍历PostgreSQL相比,完全索引遍历的效率非常低SEQ SCAN.
该JOIN谓词,而另一方面,可以使用中获益NESTED LOOPS,如果你的指数是非常有选择性的,并且使用HASH JOIN的是它的inselective.
PostgreSQL 应该通过估计行数来选择正确的.
由于您有30k针对260K行的行,我希望HASH JOIN效率更高,您应该尝试在DELETE ... USING查询上构建计划.
为了确保,请发布两个查询的执行计划.