如何强制SQL Server在WHERE子句之前处理CONTAINS子句?

时间:2011-06-22 12:48:18

标签: sql-server query-optimization

我有一个SQL查询,它使用标准WHERE子句和全文索引CONTAINS子句。查询是从代码动态构建的,包含可变数量的WHERE和CONTAINS子句。

为了使查询更快,在应用其余条件之前搜索全文索引非常重要。

但是,SQL Server选择在CONTAINS子句之前处理WHERE子句,这会导致表扫描并且查询非常慢。

我可以使用两个查询和一个临时表重写它。当我这样做时,查询执行速度提高了10倍。但我不想在创建查询的代码中这样做,因为它太复杂了。

是否有办法强制SQL Server在其他任何事情之前处理CONTAINS?我无法强制执行计划(USE PLAN),因为查询是动态构建的,并且变化很大。

注意:我在SQL Server 2005和SQL Server 2008上遇到同样的问题。

3 个答案:

答案 0 :(得分:1)

您可以像这样向

发信号通知您的意图
SELECT
   *
FROM
    (
    SELECT *
    FROM


    WHERE
       CONTAINS
    ) T1
WHERE
   (normal conditions)

但是,SQL是声明性的:你说你想要什么,而不是如何来做。因此,优化器可能会决定忽略上面的嵌套。

在应用经典WHERE子句之前,您可以强制使用CONTAINS实现派生表。我不保证表现。

SELECT
   *
FROM
    (
    SELECT TOP 2000000000
       *
    FROM
       ....
    WHERE
       CONTAINS
    ORDER BY
       SomeID
    ) T1
WHERE
   (normal conditions)

答案 1 :(得分:0)

尝试使用没有临时表的2个查询:

SELECT * 
FROM table
WHERE id IN (
    SELECT id 
    FROM table 
    WHERE contains_criterias
) 
AND further_where_classes

答案 2 :(得分:0)

正如我上面提到的,这并不像@gbn提出的那样,将派生表“具体化”的方式干净,但循环连接提示会强制执行评估顺序,并且过去对我有用(诚​​然,通常涉及两个不同的表)。但是有几个问题:

  • 查询很丑陋
  • 你仍然不能保证在加入之后不会评估其他WHERE参数(我有兴趣看看你得到了什么)

虽然你问过:

SELECT OriginalTable.XXX
FROM (
    SELECT XXX
    FROM OriginalTable
    WHERE 
        CONTAINS XXX
) AS ContainsCheck
INNER LOOP JOIN OriginalTable 
    ON ContainsCheck.PrimaryKeyColumns = OriginalTable.PrimaryKeyColumns
        AND OriginalTable.OtherWhereConditions = OtherValues