我参加了我学校的数据库课程。老师给了我们一个简单的练习:考虑以下简单的模式:
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"
当我要求解释时,我得到的只是"如果你更加关注课程,你会知道为什么" 。辉煌。
那么,为什么我的答案不对?什么完全这些查询之间的区别是什么?在数据库引擎级别上他们做了什么完全?
答案 0 :(得分:27)
那么,为什么我的答案不对?
您回答 正确。
我的猜测为什么老师将其标记为错误,他/她试图在该问题上练习使用连接。但如果是有意的话,那应该是问题的一部分。
这些查询之间究竟有什么区别
从技术上讲,他们确实不同。具有简单查询优化器的DBMS将以与教师答案中的连接不同的方式检索子选择。
如果具有良好优化程序的DBMS实际上可能为两个查询提出相同的执行计划,我不会感到惊讶。
我创建了一些包含50000本书,50000位作者和7种不同类型的测试数据进行测试(较小的数字并不真正有意义,因为优化器倾向于简单地抓住整个表格)。该语句将返回7144行。
执行计划几乎与“join”方法中的一些小变化相同。
以下是子选择版本的计划:http://explain.depesz.com/s/eov
以下是加入版本的计划:http://explain.depesz.com/s/aTI
令人惊讶的是,加入版本的成本值略高。
两个计划都是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
作为排行榜,而对于您老师的查询,优化程序可以根据表格选择要进行排序的表格统计