jd.*_*jd. 58 postgresql performance delete postgresql-9.2
我在 PostgreSQL 9.2 上有一个数据库,它有一个包含大约 70 个表的主模式和可变数量的相同结构的每个客户端模式,每个模式有 30 个表。客户端模式具有引用主模式的外键,而不是相反。
我刚刚开始用一些从以前版本中获取的真实数据填充数据库。当我不得不在主模式的一个非常中心的表中进行批量删除时,数据库已经达到大约 1.5 GB(预计在几周内会增长到几十 GB)。所有相关的外键都标记为 ON DELETE CASCADE。
这将需要很长时间,这并不奇怪,但 12 小时后很明显,我最好重新开始,删除数据库并再次启动迁移。但是,如果我稍后需要在数据库处于活动状态且更大时重复此操作怎么办?有没有替代的、更快的方法?
如果我编写一个脚本来浏览依赖表,从离中心表最远的表开始,逐表删除依赖行,会快得多吗?
一个重要的细节是某些表上有触发器。
小智 65
我有一个类似的问题。事实证明,这些ON DELETE CASCADE触发器大大减慢了速度,因为这些级联删除非常慢。
我通过在引用表的外键字段上创建索引解决了这个问题,我从花费几个小时的时间删除到几秒钟。
Chr*_*ers 40
你有几个选择。最好的选择是运行批量删除,以免触发触发器。在删除之前禁用触发器,然后重新启用它们。这为您节省了大量时间。例如:
ALTER TABLE tablename DISABLE TRIGGER ALL;
DELETE ...;
ALTER TABLE tablename ENABLE TRIGGER ALL;
Run Code Online (Sandbox Code Playgroud)
这里的一个主要关键是您希望最小化子查询的深度。在这种情况下,您可能需要设置临时表来存储相关信息,这样您就可以避免在删除时产生深层子查询。
Mik*_*nen 29
解决问题最简单的方法是从 PostgreSQL 中查询详细时序:EXPLAIN. 为此,您至少需要找到一个完成但花费比预期时间更长的查询。假设这条线看起来像
delete from mydata where id='897b4dde-6a0d-4159-91e6-88e84519e6b6';
Run Code Online (Sandbox Code Playgroud)
而不是真正运行该命令,你可以做
begin;
explain (analyze,buffers,timing)
delete from mydata where id='897b4dde-6a0d-4159-91e6-88e84519e6b6';
rollback;
Run Code Online (Sandbox Code Playgroud)
将rollback在年底允许没有真正修改数据库运行此。您仍然可以获得详细的时间安排。运行之后,您可能会在输出中发现某些触发器会导致巨大的延迟:
...
Trigger for constraint XYZ123: time=12311.292 calls=1
...
Run Code Online (Sandbox Code Playgroud)
该time是毫秒(毫秒),因此检查这个contraint花了12.3秒。您需要INDEX在所需的列上添加一个新的,以便可以有效地计算此触发器。对于外键引用,引用另一个表的列必须被索引(即源列,而不是目标列)。PostgreSQL 不会自动为您创建此类索引,并且DELETE是您真正需要该索引的唯一常见查询。因此,您可能已经积累了多年的数据,直到遇到DELETE由于缺少索引而速度太慢的情况。
一旦您确定了该约束的性能(或其他一些花费了很长时间的事情),请在begin/rollback块中重复该命令,以便您可以将新的执行时间与之前的执行时间进行比较。继续,直到您对单行删除响应时间感到满意为止(通过添加不同的索引,我让一个查询从 25.6 秒缩短到 15 毫秒或大约快 1700 倍)。然后,您可以继续完成完全删除而无需任何黑客攻击。
(请注意,EXPLAIN需要一个可以成功完成的查询。我曾经遇到过一个问题,即 PostgreSQL 花了很长时间才发现一次删除将违反外键约束,在这种情况下EXPLAIN无法使用,因为它不会为失败发出计时查询。我不知道在这种情况下调试性能问题的任何简单方法。)
Joh*_*nn8 12
禁用触发器可能对数据库完整性构成威胁,不建议这样做;但是,如果您确定您的操作是约束故障证明,则可以禁用触发器,如下所示:
SET session_replication_role = replica;
Run Code Online (Sandbox Code Playgroud)
运行DELETE这里。
要恢复触发器,请运行:
SET session_replication_role = DEFAULT;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
79611 次 |
| 最近记录: |