繁体   English   中英

在Oracle中比较两个联接查询

[英]Comparing two join queries in Oracle

我有2个查询执行相同的工作:

SELECT * FROM student_info 
INNER JOIN class 
ON student_info.id = class.studentId 
WHERE student_info.name = 'Ken'

SELECT * FROM (SELECT * FROM student_info WHERE name = 'Ken') studInfo
INNER JOIN class 
ON student_info.id = class.studentId

哪一个更快? 我想第二个但不确定,我正在使用Oracle 11g。

更新:

我的表没有索引,并且我确认两个PLAN_TABLE_OUTPUT几乎相同:

http://i.imgur.com/wf2FnjZ.png

全尺寸图片

在最新版本的Oracle中, 优化器足够智能,足以胜任其工作。 因此,这无关紧要,并且您的两个查询都将在内部进行优化以有效地完成任务。 优化器可能会重写查询并选择有效的执行计划

让我们通过一个EMP和DEPT表的小例子来了解这一点。 我将在问题中使用两个类似的查询,例如您的查询。

我将采用两种情况,一种是具有未索引列的谓词,其次是具有索引列的谓词。

情况1-谓词具有非索引列

SQL> explain plan for
  2  SELECT * FROM emp e
  3  INNER JOIN dept d
  4  ON e.deptno = d.deptno
  5  where ename = 'SCOTT';

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Plan hash value: 3625962092

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |     1 |    59 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |         |       |       |            |          |
|   2 |   NESTED LOOPS               |         |     1 |    59 |     4   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL         | EMP     |     1 |    39 |     3   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    20 |     1   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("E"."ENAME"='SCOTT')
   4 - access("E"."DEPTNO"="D"."DEPTNO")

Note
-----
   - this is an adaptive plan

22 rows selected.

SQL>
SQL> explain plan for
  2  SELECT * FROM (SELECT * FROM emp WHERE ename = 'SCOTT') e
  3  INNER JOIN dept d
  4  ON e.deptno = d.deptno;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Plan hash value: 3625962092

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |     1 |    59 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |         |       |       |            |          |
|   2 |   NESTED LOOPS               |         |     1 |    59 |     4   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL         | EMP     |     1 |    39 |     3   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    20 |     1   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("ENAME"='SCOTT')
   4 - access("EMP"."DEPTNO"="D"."DEPTNO")

Note
-----
   - this is an adaptive plan

22 rows selected.

SQL>

情况2-谓词具有索引列

SQL> explain plan for
  2  SELECT * FROM emp e
  3  INNER JOIN dept d
  4  ON e.deptno = d.deptno
  5  where empno = 7788;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Plan hash value: 2385808155

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |     1 |    59 |     2   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |         |     1 |    59 |     2   (0)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| EMP     |     1 |    39 |     1   (0)| 00:00:01 |
|*  3 |    INDEX UNIQUE SCAN         | PK_EMP  |     1 |       |     0   (0)| 00:00:01 |
|   4 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    20 |     1   (0)| 00:00:01 |
|*  5 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("E"."EMPNO"=7788)
   5 - access("E"."DEPTNO"="D"."DEPTNO")

18 rows selected.

SQL>
SQL> explain plan for
  2  SELECT * FROM (SELECT * FROM emp where empno = 7788) e
  3  INNER JOIN dept d
  4  ON e.deptno = d.deptno;

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Plan hash value: 2385808155

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |     1 |    59 |     2   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |         |     1 |    59 |     2   (0)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| EMP     |     1 |    39 |     1   (0)| 00:00:01 |
|*  3 |    INDEX UNIQUE SCAN         | PK_EMP  |     1 |       |     0   (0)| 00:00:01 |
|   4 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    20 |     1   (0)| 00:00:01 |
|*  5 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("EMPNO"=7788)
   5 - access("EMP"."DEPTNO"="D"."DEPTNO")

18 rows selected.

SQL>

每种情况下的解释计划之间是否有区别? 没有。

您需要向我们展示查询计划和执行统计信息才能确定。 就是说,假设name已建立索引并且统计信息相当准确,那么如果两个查询没有生成相同的计划(因此具有相同的性能),我会感到震惊。 无论使用哪种查询,Oracle都可以在评估联接之前或之后自由评估谓词,因此在两种情况下不太可能选择不同的谓词。

我肯定会倾向于第一个查询。

当选择嵌套时,Oracle的优化机会更少。 它通常必须将内部选择评估为临时视图,然后将外部选择应用于该临时视图。 这几乎没有Oracle可以一起评估所有内容的JOIN更快。

显示您的解释EXPLAIN PLAN也将为我们提供更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM