0

我需要将表 B 中的行复制到表 A。要求是仅插入 A 中尚不存在的行。

我的问题是,以下两种中哪一种更有效:

一种)

   INSERT INTO A (x, y, z)
   SELECT x, y, z
   FROM B b
   WHERE b.id NOT IN (SELECT id FROM A);

二)

   INSERT INTO A (x, y, z)
   SELECT b.x, b.y, b.z
   FROM B b LEFT OUTER JOIN A a
     ON b.id = a.id
   WHERE a.id is NULL;

我假设答案取决于桌子的大小。但我想知道在使用一种方法而不是另一种方法方面是否存在明显的问题。

为了减少模糊性,假设表 B 的行数少于 50K,表 A 的大小始终等于或大于表 B 的 1-5 倍。

如果有人有其他更有效的方法来做到这一点,请告诉。

4

4 回答 4

4

要添加另一个选项:

INSERT INTO A (x, y, z)
SELECT B.x, B.y, B.z
FROM B
WHERE NOT EXISTS(SELECT * FROM A WHERE A.id = B.id)

我通常使用 LEFT JOIN 方法。但是,如果您想真正了解什么是最有效的,请在您的环境中运行一些测试。查看每种方法的执行计划是什么(您可能会发现多种方法实际上会产生相同的执行计划)。

于 2009-12-03T22:22:38.540 回答
0

没关系——一个好的优化器会一视同仁地对待这些。实际上,在这种情况下,我已经看到了古怪的执行计划,但众所周知,我可以互换使用这两种样式,具体取决于查询的心情、可读性和复杂性。

在 SQL Server 中,当您需要在不使用某种连接解决方​​法(我不推荐)的情况下对多于一个列的元组进行 JOIN 时,选项 A 不可用,这将我们带到了 cat-skinning 选项 C(我也可以使用,特别是连接真的很松散),它直接扩展到元组:

INSERT INTO A (x, y, z) 
SELECT x, y, z 
FROM B b 
WHERE NOT EXISTS (SELECT * FROM A WHERE id = b.id); 

INSERT INTO A (x, y, z) 
SELECT x, y, z 
FROM B b 
WHERE NOT EXISTS (SELECT * FROM A WHERE id1 = b.id1 AND id2 = b.id2); 
于 2009-12-03T22:24:30.440 回答
0

我认为选项 B 更好,特别是如果表 A 比表 B 大 > 1。

如果您在 a.id 和 b.id 上有索引,那么加入会更快,恕我直言,比使用 where 每一行...

于 2009-12-03T22:26:28.720 回答
0

根据行数和数据库上的活动,在插入之前删除表上的所有索引并在之后重新创建它们会很有帮助。

于 2009-12-03T22:52:57.107 回答