为什么多个WHERE条件会减慢查询速度而不是加快速度?

Cla*_*ark 17 t-sql sql-server sql-server-2005

问题是,与使用一个或两个而不是全部三个条件运行的查询相比,所讨论的查询运行速度非常慢.

现在查询.

Select Count(*)
From 
    SearchTable 
Where 
    [Date] >= '8/1/2009' 
    AND 
    [Zip] In (Select ZipCode from dbo.ZipCodesForRadius('30348', 150))
    AND 
    FreeText([Description], 'keyword list here')  
Run Code Online (Sandbox Code Playgroud)

第一个条件是自我解释.第二个使用UDF获取30348英里内150英里内的邮政编码列表.第三个使用全文索引来搜索提供的单词.

只有这种情况

[Date] >= '8/1/2009' 
Run Code Online (Sandbox Code Playgroud)

查询在3秒内返回43884(表大小不到500k行).

仅使用此条件

[Zip] In (Select ZipCode from dbo.ZipCodesForRadius('30348', 150))
Run Code Online (Sandbox Code Playgroud)

我得到27920,也在3秒后返回.

并且只有全文部分

FreeText([Description], 'keyword list here')
Run Code Online (Sandbox Code Playgroud)

68404在8秒内返回.

当我只使用邮政编码和全文条件时,我在4秒内得到4919 .
只是日期和全文条件让我在短短的14秒内得到9481 .
使用日期和邮政编码条件只能在14秒内给出3238 .
在所有三个条件下,查询在2分53秒内返回723 .(wtfbbq)

mbe*_*ish 17

了解原因的唯一方法是检查执行计划.尝试SET SHOWPLAN_TEXT ON.


Jus*_*tin 10

获得执行计划

你需要看看执行计划,以便有任何希望在了解响应时间变化的真正原因.特别是在这种情况下,有几个因素需要考虑:

  • 返回更多行的一些查询可能更快,因为它们正在进行表扫描 - 每个人都有"表扫描很慢",但根据数据分布,执行表扫描的速度可能比50,000行更快查找.没有执行扫描就无法判断.
  • 错误的统计信息也可能阻止SQL服务器准确预测它期望返回的行数 - 如果SQL服务器期望20行但是在更复杂的查询中确实有20,000个,那么它可能最终会在错误的情况下做事情订单导致查询速度非常慢 - 再次说明没有执行计划就无法判断.
  • 特别是使用Freetext全文搜索引擎的方法,这可能会导致SQL服务器在预测返回的行数方面出现其他问题.

真的,得到执行计划.

更新:

可能的原因

在没有执行计划的情况下,我认为执行缓慢的最可能原因是对条件的估计不佳ZipCodeDescription:

  • 很难估计ZipCode条件匹配的数量,因为它的结果取决于存储过程.
  • FreeText根据全文查询引擎的结果,很难估计条件匹配的数量.

我认为发生的事情是SQL服务器低估了过滤后将保留的行数,并以错误的顺序应用查询.结果是它最终会进行数十次(可能数百次)的查找,这比仅进行表扫描要慢得多.

对于一个特别复杂的查询,我看到SQL服务器执行~3,000,000次查找尝试返回单行 - 该表甚至没有3,000,000行!

要尝试的东西 - 将ZipCodeForRadius放入临时表中.

如果我是对的,那么为了帮助第一个你可以尝试将ZipCodesForRadius存储过程的结果放到一个临时表中,我不得不承认我没有一个很好的解释为什么这有所帮助,但我做有一些理论可以帮助:

  • 关于临时表的更好的统计数据
  • 它会产生副作用,导致SELECT每次运行查询时都会重新编译主语句(除非邮政编码的范围非常小) - 在proc需要几秒钟的时间,如果有很好的话,这将是一件好事.匹配邮政编码的变化.如果没有,则有防止重新编译的方法.

在任何情况下,它当然不应该造成太大的伤害.