Sql server 2008 SQL 2008:在不需要时阻止查询中的全文查找

Sql server 2008 SQL 2008:在不需要时阻止查询中的全文查找,sql-server-2008,tsql,full-text-search,short-circuiting,Sql Server 2008,Tsql,Full Text Search,Short Circuiting,在处理这种特定情况时,逻辑运算符在SQL中没有短路对我来说是个新闻 我通常在where子句中按照这些思路做一些事情(通常在处理搜索查询时): 即使在这个例子中它没有短路,这也不重要。但是,在处理全文搜索功能时,它确实很重要。。如果该查询的第二部分是CONTAINS(myTable.Description,@Description),它将不起作用,因为这些函数不允许该变量为null或空 当按顺序执行CASE的语句时,我发现了,因此我可以这样更改我的查询,以确保仅在需要时调用全文查询,同时将变量从n

在处理这种特定情况时,逻辑运算符在SQL中没有短路对我来说是个新闻

我通常在where子句中按照这些思路做一些事情(通常在处理搜索查询时):

即使在这个例子中它没有短路,这也不重要。但是,在处理全文搜索功能时,它确实很重要。。如果该查询的第二部分是
CONTAINS(myTable.Description,@Description)
,它将不起作用,因为这些函数不允许该变量为null或空

当按顺序执行
CASE
语句时,我发现了
,因此我可以这样更改我的查询,以确保仅在需要时调用全文查询,同时将变量从null更改为
”“”“
,当该变量为null时,允许执行查询:

WHERE
   (CASE WHEN @Description = '""' THEN 1 WHEN CONTAINS(myTable.Description, @Description) THEN 1 ELSE 0 END = 1)
上面的代码应该阻止全文查询执行,除非实际上有一个值可供搜索

我的问题是,如果我在@Description为
“”“
”的地方运行此查询,那么执行计划中仍有相当一部分时间用于处理聚集索引搜索和fulltextmatch,即使该表和搜索最终根本没有被使用:有没有办法避免这种情况


我试图将其从硬编码的动态查询中提取出来,并放入存储过程中,但如果该过程最终变慢,我不确定是否可以证明这一点。

这并不理想,但可能类似的方法会起作用:

IF @Description = ''
BEGIN 
     SELECT ...
END
ELSE
BEGIN
     SELECT ...
     WHERE CONTAINS(mytable.description, @Description)
END
这样可以避免mysql,并且在不需要的时候运行FT扫描


一般来说,我发现
CONTAINSTABLE
要快一点。此外,由于无论您使用的是我的解决方案还是您的解决方案,查询计划都将非常不同,因此请注意。参数嗅探是指优化器基于传入的特定参数值构建计划

如果其他人遇到这样的情况,这就是我最终要做的,这与M_M的意图非常接近;我把全文分开,放在树枝后面:

DECLARE @TableBfullSearch TABLE (TableAId int)
IF(@TableBSearchInfo IS NOT NULL)
   INSERT INTO @TableBfullSearch
   SELECT
      TableAId
   FROM
      TableB
   WHERE
   ...(fulltext search)...

DECLARE @TableCfullSearch TABLE (TableAId int)
IF(@TableCSearchInfo IS NOT NULL)
   INSERT INTO @TableCfullSearch
   SELECT
      TableAId
   FROM
      TableC
   WHERE
   ...(fulltext search)...

--main query with this addition in the where clause
SELECT
  ...
FROM
   TableA
WHERE
   ...
   AND (@TableBSearchInfo IS NULL OR TableAId IN (SELECT TableAId FROM @TableBfullSearch))
   AND (@TableCSearchInfo IS NULL OR TableAId IN (SELECT TableAId FROM @TableCfullSearch))

我认为这大概和不使用某种动态查询时一样好,因为查询中有两个可选的查找,所以我最终会有4个分支
DECLARE @TableBfullSearch TABLE (TableAId int)
IF(@TableBSearchInfo IS NOT NULL)
   INSERT INTO @TableBfullSearch
   SELECT
      TableAId
   FROM
      TableB
   WHERE
   ...(fulltext search)...

DECLARE @TableCfullSearch TABLE (TableAId int)
IF(@TableCSearchInfo IS NOT NULL)
   INSERT INTO @TableCfullSearch
   SELECT
      TableAId
   FROM
      TableC
   WHERE
   ...(fulltext search)...

--main query with this addition in the where clause
SELECT
  ...
FROM
   TableA
WHERE
   ...
   AND (@TableBSearchInfo IS NULL OR TableAId IN (SELECT TableAId FROM @TableBfullSearch))
   AND (@TableCSearchInfo IS NULL OR TableAId IN (SELECT TableAId FROM @TableCfullSearch))