首先使用的执行计划UNION
显示的步骤要少得多,不幸的是,执行计划并不是一切,还有表扫描、逻辑读取、CPU 使用率,所以这不是全部,它在很大程度上取决于您的数据和你的指数。
使用 dupes 时,第一个查询应该执行得更好,因为在UNION
连接之前删除重复项会导致对表 3 的表扫描次数减少。如果 table1 和 table2 中没有重复项,那么应该没有区别。
这可以通过一些示例数据来证明。我所有的示例都使用以下 5 个表(T4 和 T5 只是将输出转储到其中,因此您不必在 SQL fiddle 页面向下滚动数英里即可查看执行计划)
CREATE TABLE T1 (ID INT NOT NULL);
CREATE TABLE T2 (ID INT NOT NULL);
CREATE TABLE T3 (FK INT NOT NULL, SomeValue VARCHAR(10) NOT NULL);
CREATE TABLE T4 (ID INT NOT NULL, SomeValue VARCHAR(10) NULL);
CREATE TABLE T5 (ID INT NOT NULL, SomeValue VARCHAR(10) NULL);
并且全部使用以下内容进行测试(也反向完成以消除任何查询计划缓存):
INSERT INTO T4
SELECT ID, SomeValue
FROM T1
LEFT JOIN T3
ON ID = FK
UNION
SELECT ID, SomeValue
FROM T2
LEFT JOIN T3
ON ID = FK;
INSERT INTO T5
SELECT ID, SomeValue
FROM ( SELECT ID
FROM T1
UNION
SELECT ID
FROM T2
) T
LEFT JOIN T3
ON ID = FK;
示例 1 - T1 包含也在 T2 中的行
INSERT INTO T1 (ID)
SELECT *
FROM GENERATE_SERIES(0, 40000);
INSERT INTO T2 (ID)
SELECT *
FROM GENERATE_SERIES(20000, 60000);
INSERT INTO T3 (FK, SomeValue)
SELECT *, 'VALUE'
FROM GENERATE_SERIES(10000, 50000);
SQL Fiddle 上的示例显示插入到 T4(UNION
之前JOIN
)性能更好。我已经运行了 25 次,其中 22 次插入到 T4 运行得更快。没有足够的数据从等式中消除服务器负载,因此正如预期的那样,存在一些异常情况。在此示例中,插入的顺序颠倒了,再次看到了类似的结果。
示例 2 - table1 和 table2 中没有重复项
INSERT INTO T1 (ID)
SELECT *
FROM GENERATE_SERIES(0, 30000);
INSERT INTO T2 (ID)
SELECT *
FROM GENERATE_SERIES(30001, 60000);
INSERT INTO T3 (FK, SomeValue)
SELECT *, 'VALUE'
FROM GENERATE_SERIES(10000, 50000);
在这个例子中,执行时间更接近彼此,并且经常在哪种方法执行得更快之间切换。
样本数据
样本数据 2
最后,重申已经提出的观点,如果您不期望被欺骗/不关心被欺骗,那么UNION ALL
将提高性能,但是由于没有欺骗,两种方法的性能应该大致相似,这应该会改善两种方法在同等程度上。我没有对此进行测试,但更改我用来检查的测试数据应该不是一项艰巨的任务。
编辑
我刚刚尝试了 SQL Fiddle 上的查询,它们显示出的差异比在我的本地机器上的差异要大得多,所以用少许盐来处理这些示例并在您自己的服务器上进行测试,创建一个公平的要容易得多测试环境!