我有一个非常大的节点表(基数大约为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个)。
答案 0 :(得分:3)
也许做左连接,然后删除null。
所以:
DELETE ntr
FROM node_type_relations ntr
LEFT JOIN nodes n
ON n.id = ntr.node_id
WHERE n.id IS NULL
答案 1 :(得分:1)
@lynks'找到了他自己案例的最佳查询 - 使用EXISTS
半连接:
DELETE FROM node_type_relations ntr
WHERE NOT EXISTS (
SELECT 1
FROM nodes n
WHERE n.id = ntr.node_id
);
使用JOIN语法的解决方案必须在PostgreSQL中构造如下:
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;