表加入效率问题

时间:2009-05-12 15:52:25

标签: oracle performance

跨表连接时(如下例所示),连接表或加入仅包含所需列的子查询之间是否有效率差异?

换句话说,这两个表之间的效率是否存在差异?

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)

3 个答案:

答案 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”。

相关问题