来自Joel Spolsky 关于漏洞抽象的 文章:
[C]某些SQL查询比其他逻辑上等效的查询慢几千倍.一个着名的例子是,如果你指定"a = b和b = c和a = c",那么某些SQL服务器要比你只指定"where a = b和b = c"那样快得多,即使结果集也是如此是一样的.
有谁知道这个细节?
显然,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查询优化技术来重新调整查询以使它们更有效).但在现实世界中并非如此 - 数据库查询通常必须由人类重写以使其更有效.
总的来说,文章的重点是抽象只能是如此好,没有抽象是完美的.
这是一个更简单的解释,其中所有内容都在一个表中.
假设A和C都被索引,但B不是.如果优化器无法实现A = C,则必须在两个WHERE条件下使用非索引B.
但是,如果您告诉服务器a = c,它可以先有效地应用该过滤器,并大大减少工作集的大小.