来自Joel Spolsky文章的SQL问题

时间:2008-12-29 03:34:18

标签: sql query-optimization

来自Joel Spolsky的article漏洞抽象:

  

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

有谁知道这个细节?

3 个答案:

答案 0 :(得分:26)

显然,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查询优化技术来重新调整查询以使它们更有效)。但在现实世界中并非如此 - 数据库查询通常必须由人类重写以使其更有效。

总的来说,文章的重点是抽象只能是如此好,没有抽象是完美的。

答案 1 :(得分:16)

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

假设A和C都被索引,但B不是。如果优化器无法实现A = C,那么它必须在两个WHERE条件下使用非索引B。

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

答案 2 :(得分:1)

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

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