Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.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 WHERE子句中的优化似乎不适用于UNION_Sql_Sql Server_Sql Server 2014 - Fatal编程技术网

Sql WHERE子句中的优化似乎不适用于UNION

Sql WHERE子句中的优化似乎不适用于UNION,sql,sql-server,sql-server-2014,Sql,Sql Server,Sql Server 2014,我尝试了以下格式的SQL脚本。(有多个连接可以生成set1、set2和set3,但为了简单起见,删除了它们) 当@include=0时,最后一个联合将被忽略。这也是我在查找有条件地执行UNION时看到的情况 但我不是这样;即使当@include=0时,查询也需要很长时间才能执行。如果我注释掉最后一部分,查询将执行得更快 SELECT * FROM ( SELECT * FROM Set1 WHERE someConditions UNION SELECT * FR

我尝试了以下格式的SQL脚本。(有多个连接可以生成set1、set2和set3,但为了简单起见,删除了它们)

@include=0
时,最后一个
联合
将被忽略。这也是我在查找有条件地执行
UNION
时看到的情况

但我不是这样;即使当
@include=0
时,查询也需要很长时间才能执行。如果我注释掉最后一部分,查询将执行得更快

SELECT * FROM (
    SELECT * FROM Set1
    WHERE someConditions
    UNION
    SELECT * FROM Set2
    WHERE someConditions
    --UNION 
    --SELECT * FROM Set3
    --WHERE @include = 1 AND otherConditions..
) as t
ORDER BY ...
为什么编译器无法获取此信息?有没有办法在这种情况下优化查询?

对我来说,选项(重新编译)在类似的测试设置中运行得很好-在没有提示的情况下重用糟糕的计划(假设以前使用@include=1运行),但在使用重新编译时创建一个新的、更好的计划

如果这对您不起作用,您可以尝试使用If将其拆分为两个不同的语句,例如:

BEGIN
IF @include = 1 
BEGIN

    SELECT * FROM Set1
    WHERE someConditions
    UNION
    SELECT * FROM Set2
    WHERE someConditions
    UNION 
    SELECT * FROM Set3
    WHERE otherConditions..

END

ELSE 
BEGIN
    SELECT * FROM Set1
    WHERE someConditions
    UNION
    SELECT * FROM Set2
    WHERE someConditions
END
END

可以尝试使用?或使用动态SQL创建一个只包含所需部分的查询。另外,您真的需要
UNION
,还是
UNION-ALL
仍能产生正确的结果
UNION
是一种成本更高的运算符,只有在您真正需要时才应使用。这只是一种预感,但您能否尝试将所有出现的“UNION”替换为“UNION all”,然后将外部的“select”转换为“select distinct”。查询引擎可能更倾向于以这种方式分别处理这三个查询组件。
选项(重新编译)
UNION ALL
对我没有影响。可能不得不使用动态SQL作为最后手段。@eshirvana No;在末尾为整个查询添加。我们不能为内部查询添加
重新编译
,对吗?它导致语法错误。出于某种原因,重新编译对我没有帮助。但我喜欢这种拆分的想法,尽管这可能对维护没有好处。
BEGIN
IF @include = 1 
BEGIN

    SELECT * FROM Set1
    WHERE someConditions
    UNION
    SELECT * FROM Set2
    WHERE someConditions
    UNION 
    SELECT * FROM Set3
    WHERE otherConditions..

END

ELSE 
BEGIN
    SELECT * FROM Set1
    WHERE someConditions
    UNION
    SELECT * FROM Set2
    WHERE someConditions
END
END