Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何强制SQL Server在WHERE子句之前处理CONTAINS子句?_Sql Server_Query Optimization - Fatal编程技术网

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

Sql server 如何强制SQL Server在WHERE子句之前处理CONTAINS子句?,sql-server,query-optimization,Sql Server,Query Optimization,我有一个SQL查询,它使用标准WHERE子句和全文索引CONTAINS子句。查询是根据代码动态构建的,包含数量可变的WHERE和CONTAINS子句 为了快速查询,在应用其余条件之前搜索全文索引是非常重要的 但是,SQLServer选择在CONTAINS子句之前处理WHERE子句,这会导致表扫描和查询速度非常慢 我可以使用两个查询和一个临时表来重写它。当我这样做时,查询的执行速度提高了10倍。但是我不想在创建查询的代码中这样做,因为它太复杂了 有没有一种方法可以强制SQL Server在处理其他

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

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

但是,SQLServer选择在CONTAINS子句之前处理WHERE子句,这会导致表扫描和查询速度非常慢

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

有没有一种方法可以强制SQL Server在处理其他内容之前先处理包含的内容?我不能强制执行计划(使用计划),因为查询是动态生成的,并且变化很大


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

尝试使用两个不带临时表的查询:

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

你可以像这样向乐观主义者表明你的意图

SELECT
   *
FROM
    (
    SELECT *
    FROM


    WHERE
       CONTAINS
    ) T1
WHERE
   (normal conditions)
然而,SQL是声明性的:你说你想要什么,而不是怎么做。因此,乐观主义者可能会决定忽略上面的嵌套

可以在应用经典WHERE子句之前,强制将包含的派生表具体化。我不能保证性能

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

正如我前面提到的,这并不像@gbn建议的TOP子句那样“具体化”派生表,而是一个循环连接提示强制执行求值顺序,并且在过去对我很有效(必须承认,通常涉及两个不同的表)。不过,有几个问题:

  • 这个问题很难说
  • 您仍然无法保证其他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

嗯,好的,我会建议一个循环连接提示,如果包含的结果总是已知的是小的,但是这是更干净的,最好的两个世界。@ GBN:如果你使用CTE不首先强制评估?@ YCK:考虑CTE一个宏就像我的派生表。也就是说,我可以用CTE来代替。同样的结果…@gbn:有趣。我有一种明显错误的印象,认为CTE更像是一个隐式临时表,而不是一个子查询。@恶心:递归时可以,但在这种情况下,它是一个宏,可以使代码看起来更好:-)这听起来有点问题-“查询是动态构建的,变化很大”-因为这可能意味着先处理
包含
,然后再处理其他条件可能并不总是最优的,所以即使您设法束缚了优化器的手脚,也可能没有达到预期的效果。@Damien_不相信者:唯一完美的解决方案是修复SQL Server优化器本身。我不知道为什么它没有发现首先处理包含的内容会快得多。因此,任何其他解决方案都不会在所有情况下都是最优的。但是,我知道在我们的情况下,大多数情况下,先处理CONTAINS会更快。但你是对的;我不能保证。谢谢你花时间发布答案。