跨表连接时(如下例所示),连接表或加入仅包含所需列的子查询之间是否有效率差异?
换句话说,这两个表之间的效率是否存在差异?
SELECT result
FROM result_tbl
JOIN test_tbl USING (test_id)
JOIN sample_tbl USING (sample_id)
JOIN (SELECT request_id
FROM request_tbl
WHERE request_status='A') USING(request_id)
VS
SELECT result
FROM (SELECT result, test_id FROM result_tbl)
JOIN (SELECT test_id, sample_id FROM test_tbl) USING(test_id)
JOIN (SELECT sample_id FROM sample_tbl) USING(sample_id)
JOIN (SELECT request_id
FROM request_tbl
WHERE request_status='A') USING(request_id)
答案 0 :(得分:5)
唯一可以确定的方法是在打开跟踪的情况下运行它们,然后查看跟踪文件。但很可能它们将被视为相同:优化器将所有内联视图合并到主语句中并提出相同的查询计划。
答案 1 :(得分:4)
没关系。它实际上可能是WORSE,因为你正在控制一般最了解的优化器。
但是,请记住,如果您正在进行JOIN并且仅包含其中一个表的列,那么QUITE OFTEN最好将其重新编写为一系列EXISTS语句 - 因为这就是您的真实含义。 JOIN(有一些例外)将连接匹配的行,这对优化器来说要做的工作要多得多。
e.g。
SELECT t1.id1
FROM table1 t1
INNER JOIN table2 ON something = something
几乎总是
SELECT id1
FROM table1 t1
WHERE EXISTS( SELECT *
FROM table2
WHERE something = something )
对于简单查询,优化器可以将查询计划减少为相同的查询计划。在DBMS上查看。
这也是代码味道,可能应该改变:
JOIN(SELECT request_id 来自request_tbl 在哪里request_status ='A')
到
SELECT result
FROM request
WHERE EXISTS(...)
AND request_status = 'A'
答案 2 :(得分:2)
没有区别。
你可以通过在这两个语句上运行EXPLAIN PLAN来判断 - Oracle知道你想要的只是“结果”列,所以它只做了获得所需数据所需的最小值 - 你会发现计划将是相同。
Oracle优化器有时会“实现”子查询(即运行子查询并将结果保存在内存中以供以后重用),但这种情况很少见,只有当优化器认为这会导致性能提高时才会发生;无论如何,无论您是否在子查询中指定了列,Oracle都会执行此“实现”。
显然,如果存储“结果”列的唯一位置是在块中(以及其余数据),Oracle必须访问这些块 - 但它只会保留相关信息(“结果”列)和处理查询时在内存中的其他相关列,例如“test_id”。