SELECT FROM WHERE IN与多个表上的SELECT FROM相比

时间:2012-05-18 11:53:29

标签: sql

我参加了我学校的数据库课程。老师给了我们一个简单的练习:考虑以下简单的模式:

Table Book:
    Column title (primary key)
    Column genre (one of: "romance", "polar", ...)

Table Author:
    Column title (foreign key on Book.title)
    Column name
    Primary key on (title, name)

问题包括以下问题:

  

写出返回写有浪漫书籍的作者的查询。

我提出了这个答案:

select distinct name 
from Author where title in (select title from Book where genre = "romance")

然而,老师说这是错的,正确答案是:

select distinct name 
from Book, Author 
where Book.title = Author.title 
  and genre = "romance"

当我要求解释时,我得到的只是"如果你更加关注课程,你会知道为什么" 。辉煌。

那么,为什么我的答案不对?什么完全这些查询之间的区别是什么?在数据库引擎级别上他们做了什么完全

2 个答案:

答案 0 :(得分:27)

  

那么,为什么我的答案不对?

您回答 正确。

我的猜测为什么老师将其标记为错误,他/她试图在该问题上练习使用连接。但如果是有意的话,那应该是问题的一部分。

  

这些查询之间究竟有什么区别

从技术上讲,他们确实不同。具有简单查询优化器的DBMS将以与教师答案中的连接不同的方式检索子选择。

如果具有良好优化程序的DBMS实际上可能为两个查询提出相同的执行计划,我不会感到惊讶。

修改

我创建了一些包含50000本书,50000位作者和7种不同类型的测试数据进行测试(较小的数字并不真正有意义,因为优化器倾向于简单地抓住整个表格)。该语句将返回7144行。

的PostgreSQL

执行计划几乎与“join”方法中的一些小变化相同。

以下是子选择版本的计划:http://explain.depesz.com/s/eov
以下是加入版本的计划:http://explain.depesz.com/s/aTI

令人惊讶的是,加入版本的成本值略高

的Oracle

两个计划都是100%完全相同:

--------------------------------------------------------------------------------------
| Id  | Operation           | Name   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |        |  6815 |   399K|       |   273   (2)| 00:00:04 |
|   1 |  HASH UNIQUE        |        |  6815 |   399K|   464K|   273   (2)| 00:00:04 |
|*  2 |   HASH JOIN         |        |  6815 |   399K|       |   172   (2)| 00:00:03 |
|*  3 |    TABLE ACCESS FULL| BOOK   |  6815 |   166K|       |    69   (2)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| AUTHOR | 50000 |  1708K|       |   103   (1)| 00:00:02 |
--------------------------------------------------------------------------------------

查看使用autotrace时的统计数据,也没有任何区别。我没有打算真正创建一个跟踪文件来分析它,因为我不希望看到那里的差异。

如果添加book.genre上的索引,事情就不会真正改变。 Oracle坚持全表扫描(即使有100000行)。可能是因为表格不是很宽,而且很多行都适合单个页面。

PostgreSQL确实对两个语句都使用了索引,但计划之间仍然没有真正的区别。

答案 1 :(得分:15)

两个查询都有效并返回相同的内容。

您的教师使用过时(但仍然有效)的连接语法,并且您正在使用在某些数据库中效率较低的构造(例如MySQL)。

如果我是你的老师,我会把这个问题写成:

SELECT  DISTINCT name
FROM    books b
JOIN    authors a
ON      a.title = b.title
WHERE   b.genre = 'romance'

但如果课程不是MySQL优化特定的话,仍会接受您和您老师的查询。

当他/她说关注时,老师的意思是什么呢?

<强>更新

在数据库引擎级别,两个查询都将进行优化以使用相同的计划,除非数据库引擎为MySQL

MySQL中,您的查询将被强制使用Authors作为排行榜,而对于您老师的查询,优化程序可以根据表格选择要进行排序的表格统计