1

从对这种特定情况的研究来看,对我来说,逻辑运算符在 SQL 中没有短路是个新闻。

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

WHERE
   (@Description IS NULL OR @Description = myTable.Description)

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

我发现 的WHEN语句CASE是按顺序执行的,所以我可以像这样更改我的查询以确保仅在需要时调用全文查找,同时将变量从 null 更改'""'为 null 以允许执行查询:

WHERE
   (CASE WHEN @Description = '""' THEN 1 WHEN CONTAINS(myTable.Description, @Description) THEN 1 ELSE 0 END = 1)

上面的代码应该阻止全文查询片段的执行,除非实际上有一个值可以搜索。

我的问题是,如果我在 @Description 所在的位置运行此查询,'""'则执行计划中仍有相当多的时间用于处理聚集索引查找和全文匹配,即使该表和搜索最终没有被使用:有没有办法避免这种情况?

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

4

2 回答 2

0

这并不理想,但也许这样的事情会起作用:

IF @Description = ''
BEGIN 
     SELECT ...
END
ELSE
BEGIN
     SELECT ...
     WHERE CONTAINS(mytable.description, @Description)
END

这样您就可以避免使用 mysql 并在不需要时运行 FT 扫描。

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

于 2011-11-04T18:58:16.403 回答
0

万一其他人遇到这样的情况,这就是我最终要做的,这与 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))

我认为这可能与没有某种动态查询的情况一样好

于 2011-11-04T20:13:10.087 回答