查询计划错误

Ben*_*Ben 3 performance sql-server sql-server-2014 query-performance

我有一个有趣的情况。我使用带有 SP1 的 SQL2014 企业版。以下查询会产生错误消息:

查询处理器耗尽了内部资源,无法生成查询计划。这是一种罕见的事件,仅适用于极其复杂的查询或引用大量表或分区的查询。请简化查询。如果您认为自己错误地收到了此消息,请联系客户支持服务以获取更多信息。

查询在没有插入语句的情况下运行良好。如果我交换 where 子句,查询也会运行,比如在exists 语句[step] = 1之后的exists 语句[step] = 3。实际上 SQL 是动态生成的,因此交换 where 子句中的顺序对我来说不是解决方案。这在 SQL 2008 和 SQL 2012 中运行良好。

推荐针对此问题的任何想法/解决方案,我感谢您的时间和精力。

insert into tblPatientConditions (
    cmrn_id
    ,metricmnemonic
    ,metricname
    ,status
    ,adddate
    )
select cmrn_id
    ,'PBLEHTN'
    ,'PossibleHTN'
    ,1
    ,Getdate()
from tblPatientInfo pers
where exists (
        select *
        from tblPatientDiagnosisCriteria
        where cmrn_id = pers.cmrn_id
            and metricname = 'PossibleHTN'
            and category = 'CLAIMS'
            and [step] = 1
            and testname = 'HTN'
        )
    and exists (
        select *
        from tblPatientDiagnosisCriteria
        where cmrn_id = pers.cmrn_id
            and metricname = 'PossibleHTN'
            and category = 'PROBLIST'
            and [step] = 2
            and testname = 'HTN'
        )
    and exists (
        select *
        from tblPatientDiagnosisCriteria
        where cmrn_id = pers.cmrn_id
            and metricname = 'PossibleHTN'
            and category = 'CLAIMS'
            and [step] = 3
            and testname = 'HTN'
        )
    and (
        exists (
            select *
            from tblPatientDiagnosisCriteria
            where cmrn_id = pers.cmrn_id
                and metricname = 'PossibleHTN'
                and category = 'DEFINITION'
                and [step] = 4
                and testname = 'SBPRECENT'
            )
        or exists (
            select *
            from tblPatientDiagnosisCriteria
            where cmrn_id = pers.cmrn_id
                and metricname = 'PossibleHTN'
                and category = 'DEFINITION'
                and [step] = 5
                and testname = 'DBPRECENT'
            )
        )
    and (
        exists (
            select *
            from tblPatientDiagnosisCriteria
            where cmrn_id = pers.cmrn_id
                and metricname = 'PossibleHTN'
                and category = 'DEFINITION'
                and [step] = 6
                and testname = 'SBPRECENT'
            )
        or exists (
            select *
            from tblPatientDiagnosisCriteria
            where cmrn_id = pers.cmrn_id
                and metricname = 'PossibleHTN'
                and category = 'DEFINITION'
                and [step] = 7
                and testname = 'DBPSECOND'
            )
        )
Run Code Online (Sandbox Code Playgroud)

SQL 是根据一组规则生成的。还生成了 14 条动态 SQL 语句来识别某些医疗状况,所有这些查询都可以正常工作。只是这个失败了,仅用于插入到表中。我也试过 SELECT INTO #table FROM 但失败了。

Kin*_*hah 7

在 SQL Server 2014 中,引入了新的基数估计逻辑。

来自 BOL :

基数估计逻辑(称为基数估计器)在 SQL Server 2014 中重新设计,以提高查询计划的质量,从而提高查询性能。新的基数估计器结合了适用于现代 OLTP 和数据仓库工作负载的假设和算法。它基于对现代工作负载的深入基数估计研究,以及我们在过去 15 年改进 SQL Server 基数估计器的经验。来自客户的反馈表明,虽然大多数查询将从更改中受益或保持不变,但与之前的基数估计器相比,少数查询可能会出现回归

最近,我们从 SQL Server 2012 升级到 SQL Server 2014 并受到新基数估计器的影响 - 查询超时,cpu 挂钩接近 100%。

经过多次故障排除、更新统计信息、重建索引、进行查询计划分析,我们发现将兼容级别更改为 sql 2012 效果很好。

Paul White 解释 -多个谓词的基数估计

如果数据库兼容性级别设置为低于 120,或者如果跟踪标志 9481 处于活动状态,则 SQL Server 2014 中的选择性计算的行为与以前的版本相同(跟踪标志 4137 的工作方式与以前相同)。

所以我的建议是

  • 对于揭示问题的少量查询,请使用 QUERYTRACEON(9481) 提示。
  • 如果您不想赌博,那么只需将跟踪标志TF9481作为启动参数,这样它就会在服务器重新启动期间保持不变。

注意:启用后TF 9481,您无需将数据库的兼容级别设置为较低级别。

来自KB2801413

9481:在使用默认数据库兼容级别 120 运行 SQL Server 2014 时使用。跟踪标志 9481 强制查询优化器在创建查询计划时使用基数估计器的版本 70(SQL Server 2012 版本)。

作为旁注,除了适当的测试之外,您还想查看TF4199(将其视为打开查询优化器的每个修复程序的主键)。TF4199 行为随 sql server 2016 发生变化。. TF4199 对我的环境有很大帮助,并且默认情况下对所有新安装都启用。

  • @Ben 不要忘记 [接受这个答案](http://dba.stackexchange.com/help/someone-answers) 因为它解决了你的问题并解释了一些东西:) (3认同)