将行从一个表插入到另一个表中,哪个 sql 更有效(外连接 vs 顺序扫描)
Posted
技术标签:
【中文标题】将行从一个表插入到另一个表中,哪个 sql 更有效(外连接 vs 顺序扫描)【英文标题】:inserting rows from one table to another, which sql is more efficient (outer join vs sequential scan) 【发布时间】:2010-12-23 00:51:02 【问题描述】:我需要将表 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);
B)
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 倍。
如果有人有任何其他更有效的方法来做到这一点,请告诉。
【问题讨论】:
如果您使用的是具有良好查询优化器的数据库系统,那没关系。 【参考方案1】:根据行数和数据库上的活动,在插入之前删除表上的所有索引并在之后重新创建它们会很有帮助。
【讨论】:
【参考方案2】:我认为选项 B 更好,特别是如果表 A 比表 B 大 > 1 倍。
如果您在 a.id 和 b.id 上有索引,那么加入会更快,恕我直言,比使用 where 为每一行...
【讨论】:
但这取决于优化器 - 如果优化器做得好,它们可能会出现相同的结果 我同意优化器,但帮助他一点也无妨:)【参考方案3】:没关系 - 一个好的优化器会一视同仁地对待这些。实际上,在这种情况下,我已经看到了古怪的执行计划,但众所周知,我可以根据心情、可读性和查询的复杂性交替使用这两种样式。
在 SQL Server 中,当您需要在不使用某种连接解决方法(我不推荐)的情况下对多于一个列的元组进行 JOIN 时,选项 A 不可用,这将我们带到猫换肤选项 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);
【讨论】:
【参考方案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 方法。但是,如果您想真正了解什么是最有效的,请在您的环境中运行一些测试。查看每种方法的执行计划是什么(您可能会发现多种方法实际上会产生相同的执行计划)。
【讨论】:
以上是关于将行从一个表插入到另一个表中,哪个 sql 更有效(外连接 vs 顺序扫描)的主要内容,如果未能解决你的问题,请参考以下文章