我是一个老派的MySQL用户,总是更喜欢JOIN而不是子查询。但是现在每个人都用子查询,我讨厌它;我不知道为什么。

我缺乏理论知识来判断是否有任何不同。子查询是否与JOIN一样好,因此没有什么可担心的?


当前回答

我不是关系数据库专家,所以对此持保留态度。

子查询与连接的一般思想是较大查询的求值路径。

为了执行较大的查询,必须首先执行每个子查询,然后将结果集存储为与较大查询交互的临时表。

这个临时表没有索引,因此,任何比较都需要扫描整个结果集。

相反,当您使用连接时,所有索引都在使用中,因此,比较需要遍历索引树(或哈希表),这在速度方面成本要低得多。

现在,我不知道最流行的关系引擎的新版本是否在反向执行求值,只是将必要的元素加载到临时表中,作为优化方法。

其他回答

MSDN文档SQL Server说

Many Transact-SQL statements that include subqueries can be alternatively formulated as joins. Other questions can be posed only with subqueries. In Transact-SQL, there is usually no performance difference between a statement that includes a subquery and a semantically equivalent version that does not. However, in some cases where existence must be checked, a join yields better performance. Otherwise, the nested query must be processed for each result of the outer query to ensure elimination of duplicates. In such cases, a join approach would yield better results.

所以如果你需要

select * from t1 where exists select * from t2 where t2.parent=t1.id

尝试使用join代替。在其他情况下,这没有什么区别。

我说:为子查询创建函数可以消除混乱的问题,并允许您为子查询实现额外的逻辑。因此,我建议尽可能为子查询创建函数。

代码中的混乱是一个大问题,几十年来业界一直在努力避免它。

只有当第二个连接表的数据明显多于主表时,才会出现这种差异。我有过这样的经历……

我们有一个用户表,有10万个条目,他们的会员数据(友谊)大约有30万个条目。这是一个join语句,目的是获取好友及其数据,但有很大的延迟。但是当成员表中只有少量数据时,它工作得很好。一旦我们将其更改为使用子查询,它就可以正常工作。

但与此同时,连接查询正在处理比主表拥有更少条目的其他表。

所以我认为连接和子查询语句工作得很好,这取决于数据和情况。

摘自MySQL手册(13.2.10.11将子查询重写为连接):

LEFT [OUTER] JOIN可以比等效的子查询更快,因为服务器可以更好地优化它——这不是MySQL服务器独有的事实。

所以子查询可能比LEFT [OUTER] JOIN慢,但在我看来,它们的优势是可读性略高。

子查询是解决“从A获取事实,以B的事实为条件”这种形式的问题的逻辑正确方法。在这种情况下,在子查询中插入B比进行连接更具逻辑意义。从实际意义上讲,它也更安全,因为您不必担心由于与B的多个匹配而从a获得重复的事实。

然而,实际上,答案通常归结于性能。当给出连接和子查询时,一些优化器会很糟糕,而另一些则相反,这是特定于优化器、特定于dbms版本和特定于查询的。

从历史上看,显式连接通常会胜出,因此已经建立的智慧是连接更好,但优化器一直在变得更好,因此我更喜欢先以逻辑一致的方式编写查询,然后在性能限制的情况下重新构造查询。

现在,许多dbs都可以优化子查询和连接。因此,您只需使用explain检查您的查询,看看哪个更快。如果在性能上没有太大的差异,我更喜欢使用子查询,因为它们简单,更容易理解。