12

来自 Joel Spolsky 关于泄漏抽象的文章:

[C] 某些 SQL 查询比其他逻辑等效查询慢数千倍。一个著名的例子是,如果你指定“where a=b and b=c and a=c”,一些 SQL 服务器会比只指定“where a=b and b=c”快得多,即使结果集也是如此。是一样的。

有谁知道这件事的细节?

4

3 回答 3

27

显然,a = b 和 b = c => a = c - 这与传递闭包有关。Joel 的观点是某些 SQL 服务器在优化查询方面很差,因此某些 SQL 查询可能会像示例中那样使用“额外”限定符编写。

在这个例子中,请记住上面的 a、b 和 c 经常引用不同的表,并且像 a=b 这样的操作是作为连接执行的。假设表 a 中的条目数为 1000,b 为 500,c 为 20。然后 a、b 的连接需要 1000x500 行比较(这是我的愚蠢示例;实际上可能有更好的连接算法可以降低复杂性很多),并且 b,c 需要 500x20 比较。优化编译器将确定应首先执行 b,c 的连接,然后应在 a = b 上连接结果,因为 b=c 的预期行数较少。(b=c) 和 (a=b) 总共有大约 500x20 + 500x1000 的比较。之后,必须在返回的行之间计算交集(我猜也是通过连接,但不确定)。

假设 Sql 服务器可以有一个逻辑推理模块,该模块也可以推断这意味着 a = c。然后它可能会执行 b,c 的连接,然后执行 a,c 的连接(这也是一个假设情况)。这将进行 500x20 + 1000x20 比较,然后进行交集计算。如果预期 #(a=c) 较小(由于一些领域知识),那么第二个查询会快很多。

总的来说,我的答案已经变得太长了,但这意味着 SQL 查询优化不是一件容易的事,这就是为什么一些 SQL 服务器可能做得不好的原因。

更多信息可以在http://en.wikipedia.org/wiki/Query_optimizer或从一些期望的数据库中找到。

但从哲学上讲,SQL(作为一种抽象)旨在隐藏实现的所有方面。它本来是声明性的(SQL 服务器本身可以使用 sql 查询优化技术来重新表述查询以提高效率)。但在现实世界中并非如此——数据库查询通常必须由人工重写以提高效率。

总的来说,这篇文章的重点是一个抽象只能这么好,没有一个抽象是完美的。

于 2008-12-29T03:59:33.280 回答
18

这是一个更简单的解释,所有内容都在一个表中。

假设 A 和 C 都被索引,但 B 没有。如果优化器无法意识到 A = C,那么它必须对两个 WHERE 条件都使用非索引 B。

但是,如果您随后告诉服务器 a=c,它可以首先有效地应用该过滤器并大大减少工作集的大小。

于 2008-12-29T15:21:59.267 回答
1

我认为“确定”这个词是这里的操作术语。为了让优化器真正理解 a=c,它必须解析 a 的相等性并将其连接到传递关系中的“c”,以便推断出这种关系。

我认为在未来,SQL 优化器可能会变得如此聪明(如果他们还没有的话),所以 IMO 这并不是 Joel 的真正一般性声明。

于 2008-12-29T03:56:55.047 回答