确定查询中的操作顺序

时间:2014-02-14 15:17:51

标签: sql-server sql-server-2008 tsql

说我有这样的查询:

SELECT * 
FROM Foo
WHERE Name IN ('name1', 'name2') 
  AND (Date<'2013-01-01' AND Date>'2010-01-01') 
  AND Type = 1

有没有办法强制SQL服务器按照我确定的顺序来评估表达式,而不是查询优化器所说的内容?例如,我希望首先评估IN子句,然后评估Type = 1评估的输出,最后确定日期,完全按顺序排列。

2 个答案:

答案 0 :(得分:5)

是的,这在很大程度上是可能的(虽然有一些警告和反例discussed in the answers here

SELECT *
FROM   Foo
WHERE  1 = CASE
             WHEN Name IN ( 'name1', 'name2' ) THEN
               CASE
                 WHEN Type = 1 THEN
                   CASE
                     WHEN ( Date < '2013-01-01'
                            AND Date > '2010-01-01' ) THEN 1
                   END
               END
           END 

但为什么要这么麻烦?只有非常有限的情况我可以看到这是有用的(例如,如果先前的谓词评估为0,则防止除以零)。

将谓词包装起来会使查询完全无法查找,并阻止三个(否则为sargable)谓词中的任何一个使用索引。它保证读取所有行的完整扫描。

要查看此

的示例
CREATE TABLE Foo
  (
     Id     INT IDENTITY PRIMARY KEY,
     Name   VARCHAR(10),
     [Date] DATE,
     [Type] TINYINT,
     Filler CHAR(8000) NULL
  )

CREATE NONCLUSTERED INDEX IX_Name
  ON Foo(Name)

CREATE NONCLUSTERED INDEX IX_Date
  ON Foo(Date)

CREATE NONCLUSTERED INDEX IX_Type
  ON Foo(Type)

INSERT INTO Foo
            (Name,
             [Date],
             [Type])
SELECT TOP (100000) 'name' + CAST(0 + CRYPT_GEN_RANDOM(1) AS VARCHAR),
                    DATEADD(DAY, 7 * CRYPT_GEN_RANDOM(1), '2012-01-01'),
                    0 + CRYPT_GEN_RANDOM(1)
FROM   master..spt_values v1,
       master..spt_values v2 

然后在问题与此查询中运行原始查询,提供计划

enter image description here

请注意,第二个查询的成本为100%的批次成本。

查询优化器留给自己的设备首先寻找与type谓词匹配的414行,并将其用作哈希表的构建输入。然后它寻找与name匹配的728行,看它是否与哈希表中的任何内容匹配,对于4,它执行其他列的键查找并评估Date谓词。最后它返回单个匹配行。

第二个查询只是遍历表中的所有行,并按所需顺序评估谓词。读取的页数差异非常大。

原始查询

Table 'Foo'. Scan count 3, logical reads 23,
Table 'Worktable'. Scan count 0, logical reads 0

嵌套案例

Table 'Foo'. Scan count 1, logical reads 100373

答案 1 :(得分:-1)

简答:不!

您可以尝试使用括号,提示,研究查询计划等。

但这样对付引擎/优化器是否明智? 你需要大量的学习和经验才能超越优化器,也就是说,请让引擎为你处理这些细节。