SQL Natural Join和嵌套的SELECT查询

时间:2013-03-11 03:42:08

标签: sql oracle natural-join

什么可能使这两个查询不同?

帖子确实主要是代码。

SELECT DISTINCT S.name 
FROM 
    student S NATURAL JOIN taking NATURAL JOIN 
    (select * from class where classnum ='121') 
WHERE 
    department='CMPSC' 
    AND semester='Spring 2013';



SELECT DISTINCT S.name 
FROM 
    student S NATURAL JOIN taking NATURAL JOIN class 
WHERE 
    department='CMPSC' 
    AND semester='Spring 2013' 
    AND classnum='121';

谢谢!

编辑:

作为对explain命令请求的响应:我必须在ORACLE上执行此操作,因此我不确定这是否是预期的结果:

这是第一个查询:

Plan hash value: 3259400360

------------------------------------------------------
| Id  | Operation                     | Name         |
------------------------------------------------------
|   0 | SELECT STATEMENT              |              |
|   1 |  HASH UNIQUE                  |              |
|   2 |   NESTED LOOPS                |              |
|   3 |    NESTED LOOPS               |              |
|   4 |     TABLE ACCESS FULL         | CLASS        |
|   5 |     INDEX FULL SCAN           | SYS_C0099014 |
|   6 |    TABLE ACCESS BY INDEX ROWID| STUDENT      |
|   7 |     INDEX UNIQUE SCAN         | SYS_C0098998 |
------------------------------------------------------

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

   4 - filter("CLASSNUM"=121 AND "CLASS"."SEMESTER"='Spring 2013' AND
              "CLASS"."DEPARTMENT"='CMPSC')

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
   5 - access("TAKING"."SCHEDULENUM"="CLASS"."SCHEDULENUM" AND
              "TAKING"."SEMESTER"='Spring 2013')
       filter("TAKING"."SEMESTER"='Spring 2013' AND
              "TAKING"."SCHEDULENUM"="CLASS"."SCHEDULENUM")
   7 - access("S"."STUDENTNUM"="TAKING"."STUDENTNUM")

第二个QUERY:

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 226170808

-------------------------------------------------------
| Id  | Operation                      | Name         |
-------------------------------------------------------
|   0 | SELECT STATEMENT               |              |
|   1 |  HASH UNIQUE                   |              |
|   2 |   HASH JOIN                    |              |
|   3 |    MERGE JOIN                  |              |
|   4 |     TABLE ACCESS BY INDEX ROWID| STUDENT      |
|   5 |      INDEX FULL SCAN           | SYS_C0098998 |
|   6 |     SORT JOIN                  |              |
|   7 |      INDEX FULL SCAN           | SYS_C0099014 |
|   8 |    TABLE ACCESS FULL           | CLASS        |
-------------------------------------------------------

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

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

   2 - access("TAKING"."SEMESTER"="CLASS"."SEMESTER")
   6 - access("S"."STUDENTNUM"="TAKING"."STUDENTNUM")
       filter("S"."STUDENTNUM"="TAKING"."STUDENTNUM")
   7 - access("TAKING"."SEMESTER"='Spring 2013')
       filter("TAKING"."SEMESTER"='Spring 2013')
   8 - filter("CLASS"."CLASSNUM"=121 AND "CLASS"."SEMESTER"='Spring 2013' AND
              "CLASS"."DEPARTMENT"='CMPSC')

1 个答案:

答案 0 :(得分:0)

如果性能问题,那是因为你正在击败索引。执行子查询时,服务器可以使用索引来检索结果;但是,它无法索引子查询的结果,从而导致性能下降。一般来说,试图“智取”优化器的尝试效果不佳 - 您最终会得到难以阅读的查询并执行完全相同的操作(优化程序会将查询优化为与原来相同的内容)或者您最终会遇到性能更差的情况。 JOIN子句应该用于定义连接,而不是约束数据。

优化器将以相同的方式执行以下查询:

SELECT *
FROM foo f
  JOIN bar b
    ON f.id = b.id
      AND b.col = 'baz'

SELECT *
FROM foo f
  JOIN bar b
    ON f.id = b.id
WHERE b.col = 'baz'

,而

SELECT *
FROM foo f
  JOIN (
    SELECT *
    FROM bar b
    WHERE col = 'baz'
  ) AS b
  ON f.id = b.id

本质上在mysql中生成一个非索引的内存临时表。它在sql server中执行与前两个相同的操作。