SQL 查询时间复杂度 - 连接与子查询

Posted

技术标签:

【中文标题】SQL 查询时间复杂度 - 连接与子查询【英文标题】:SQL Query Time Complexity - Join vs Sub Query 【发布时间】:2018-02-08 12:58:46 【问题描述】:

我的问题是关于使用joinsub-query 方法给出相同结果时的困境,

哪个更好更快? 纯粹时间复杂度而言)

join 是否采用 O(M+N) 时间复杂度? sub-query接受O(M*N)吗?

我这样想错了吗?如果是,请纠正我。

这里,(M, N) 是两个表中的行数,组合得到的结果。

我正在寻找基于 SQL 标准的答案,而不仅仅是 mysql

P.S - 我已经完成了this 问题及其所有答案。它本质上并不关心时间复杂度部分。

【问题讨论】:

MySQL(和其他 RDMS)中的查询计划模块非常复杂,以至于对这个问题唯一可以想到的答案是“视情况而定”。规划器可以将一些查询从子查询形式转换为连接形式。别人不能。索引和表基数都会影响查询计划者的决策。 关于 O(M+N) 和 O(M*N) 部分的任何提示? @O.Jones 一般来说连接性能更好..但正如 O.Jones 所建议的那样..“取决于” 在大多数现代数据库中,查询优化器足够聪明,可以在任何一种情况下创建最佳执行计划。有时,如果可能,子查询将与连接一样执行。 关于 O(M+N) 和 O(M*N) 部分的任何提示? (时间复杂度 w.r.t 行数)。我在一篇文章中读到,编译器可以在连接中使用散列技术,而在子查询中则不然。 @scaisEdge 【参考方案1】:

join 需要 O(M+N) 时间复杂度吗?并且子查询需要 O(M*N) 吗? 我这样想有错吗?

是的,恕我直言,你这样想是错误的。 SQL 是声明性的。您使用它来声明您想要的结果,服务器会根据可用的索引和数据结构找出提供该结果的最佳方式——以满足您的查询。

几千年——真的! -- 开发人员的努力已经投入到找出各种算法、优化和技巧,以降低服务器用来满足查询的过程的复杂性。

随着数千年经验的积累,相关子查询和连接查询之间的性能差异变得不那么重要了。

由于特定原因,您的想法是错误的:您是在程序性地思考, 而不是声明性地思考。 例如,当您断言可以满足特定类型的查询时,@ 987654321@时间,您正在对用于满足它的程序进行假设。几代开发人员一直致力于让您的假设出错。

当然,可以创建具有病态性能特征的表、索引和查询。它一直在发生。但是有人修复了一个索引,问题就解决了。

【讨论】:

我能想到的最佳答案。!!感谢@O Jones 说明具体原因。现在明确了这个概念。 这当然是 100% 正确的……理论上。在实践中,有一些声明性模式被解析为 AST,查询优化器不容易将其转换为高性能执行。 相关子查询就是这样一个例子。出于这个确切原因,某些 RDBMS 甚至不支持该语法(例如,截至 2020 年 6 月的 Snowflake)【参考方案2】:

据我了解性能应该是一样的。在您的表上应用正确的索引和集群更为重要。

【讨论】:

关于 O(M+N) 和 O(M*N) 部分的任何提示? (时间复杂度 w.r.t 行数)。我在一篇文章中读到,编译器可以在连接中使用散列技术,而在子查询中则不然。

以上是关于SQL 查询时间复杂度 - 连接与子查询的主要内容,如果未能解决你的问题,请参考以下文章

具有复杂连接的sql查询

sql MS SQL内部连接与子查询与CTE

复杂的sql连接查询

SQL 查询中表的复杂连接

将具有许多连接的复杂 SQL 查询转换为 Eloquent

复杂的 SQL 连接查询 - 获取最新行