1

我有一个非常大的节点表(基数约为 600,000),该表中的每条记录都可以有一个或多个与之关联的类型。有一个node_types表包含这些(大约 30 个)类型定义。

为了连接这两者,我有一个名为node_type_relations的第三个表,它只是将节点 ID 链接到类型 ID。

我试图在剔除节点表后清理孤立的 node_type_relation 条目。我删除节点不再存在的任何类型关系的查询是;

DELETE FROM node_type_relations WHERE node_id NOT IN (SELECT id FROM nodes)

但是从它的运行速度来看(每 10 秒左右删除一条记录),看起来 Postgres 为 node_type_relations 表中的每条记录(大约 140 万条记录)加载整个节点表)。

当我想我会在这里询问是否可以以某种方式将查询从内到外翻转时,我正要潜入并编写一些代码以更明智地执行此操作。任何避免多次加载节点表的方法。

一如既往地感谢。


使用解决方案编辑

执行查询;

DELETE FROM node_type_relations WHERE NOT EXISTS (SELECT 1 FROM nodes WHERE nodes.id=node_type_relations.node_id)

似乎已经达到了预期的效果,并在几秒钟内删除了所有孤立的记录(大约 170,000 条)。

4

2 回答 2

3

也许做一个左连接,然后删除where null。

所以:

 DELETE ntr
 FROM node_type_relations ntr
 LEFT JOIN nodes n
 ON n.id = ntr.node_id
 WHERE n.id IS NULL
于 2012-06-26T13:19:55.633 回答
1

@lynks 自己为他的案例找到了最佳查询 - 使用EXISTS半连接:

DELETE FROM node_type_relations ntr
WHERE  NOT EXISTS (
   SELECT 1
   FROM   nodes n
   WHERE  n.id = ntr.node_id
   );

在 PostgreSQL 中必须像这样构造一个带有 JOIN 语法的解决方案:

DELETE FROM node_type_relations d
USING  node_type_relations ntr
LEFT   JOIN nodes n ON n.id = ntr.node_id
WHERE  ntr.node_id = d.node_id
AND    n.id IS NULL;
于 2012-06-26T19:46:15.677 回答