【问题标题】:SQL Server Full Text Search With NULL Parameters - performace hit使用 NULL 参数的 SQL Server 全文搜索 - 性能下降
【发布时间】:2015-12-28 20:27:51
【问题描述】:

我正在尝试在搜索过程中使用Contains()。全文索引已创建并正在运行。出现问题是因为您不能在 NULL 变量或参数上使用 Contains() 调用,它会引发错误。

这需要 9 秒才能运行(传入非空参数):

--Solution I saw on another post    
IF @FirstName is null OR @FirstName = '' SET @FirstName = '""'
    ...
    Select * from [MyTable] m
    Where
    (@FirstName = '""' OR CONTAINS(m.[fname], @FirstName))

这会立即运行(传入非空参数)

IF @FirstName is null OR @FirstName = '' SET @FirstName = '""'
...
Select * from [MyTable] m
Where
CONTAINS(m.[fname], @FirstName)

只需在“包含”前面添加额外的“或”,就完全改变了查询计划。我也尝试过使用“case”语句而不是“OR”,但无济于事,我仍然得到缓慢的查询。

有没有人解决过全文搜索中的空参数问题或遇到我的问题?任何想法都会有所帮助,谢谢。

我使用的是 SQL Server 2012

【问题讨论】:

  • 这 2 个查询返回相同的结果?
  • 是的,它们返回相同的结果。

标签: stored-procedures sql-server-2012 full-text-search query-optimization


【解决方案1】:

您正在检查 SQL 中绑定变量的值。更糟糕的是,您在 OR 中使用访问谓词执行此操作。我不是 SQL Server 方面的专家,但这通常是一种不好的做法,并且此类谓词会导致全表扫描。

如果您确实需要在@FirstName 为空时从表中选择所有值,请在 SQL 查询之外检查它。

IF @FirstName is null 
  <query-without-CONTAINS>
ELSE
  <query-with-CONTAINS>

我相信,在大多数情况下,@FirstName 不为空。这样,您将在大多数情况下使用全文索引访问表。无论如何,从表中获取所有行都是一个失败的原因。

【讨论】:

  • 好的,谢谢,所以不可能做我想做的事吗?在不需要时进行空检查而不运行 Contains()?这只是实际过程的一个 sn-p,我有大约 8 个全文搜索参数进来,大多数可能是空的。我想我将不得不使用动态 sql 来构建一个字符串,然后执行 EXEC sp_executesql。这基本上可以做到你所说的,而无需重复太多代码。
  • 基本上,您最终会一直执行全表扫描,所以我认为这不是一个好主意。仅在需要时添加 CONTAINS 的动态 SQL 看起来不错。
【解决方案2】:

从逻辑的角度来看,第一个查询需要更长的时间来执行,因为它必须评估 2 个条件:

@FirstName = '""' 

并且,如果第一个条件失败,这应该是大多数时候,

CONTAINS(m.[fname], @FirstName) 

我的猜测是,在您的表中,您没有任何 null 或空 FirstName,这就是结果相同的原因。否则,结果集中会有几个“”作为 FirstName。

也许您应该尝试颠倒顺序,看看是否有任何不同:

WHERE (CONTAINS(m.[fname], @FirstName) OR @FirstName = '""')

【讨论】:

  • 例如,在这两个查询中,我将“Chris”作为@FirstName 传递。两个结果完全相同。第二个查询所做的就是在尝试运行 Contains() 部分之前检查参数是否为空,以确保未传递 NULL,这将导致错误。
  • 感谢您的想法。颠倒顺序的问题是当我的参数实际上为空时我失去了“短路”,然后我会得到一个错误。进行检查首先绕过必须调用 Contains()
  • 我很困惑。当您的参数为空时,FirstName 是不是设置为双引号,就像在您的 IF 语句中一样?
  • 是的,它在 null 时设置为双引号。当参数为 null 时,我希望它返回所有内容,当 @FirstName 有值时,我希望它使用“Contains()”方法过滤我的结果。
  • 那么您可能应该将其设置为空字符串 ( ' ' ) 而不是双引号,并在 WHERE 子句中省略 @FirstName 条件。或者,按照那个年轻人的回答..
猜你喜欢
  • 2011-09-21
  • 2011-03-19
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 2018-10-21
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
相关资源
最近更新 更多