带PLAN PER VALUE提示的未知SQL查询来源排查及参数错误问题
问题
我的应用通过EF Core执行以下SQL查询:
(@orgId bigint,@contractNumber nvarchar(12)) Select top 1 * From ReceivableCut c with (nolock) Where 1=1 And c.ReceivableCutIndicator = 0 And c.OrgId = @orgId And c.ContractNumber = @contractNumber And exists (select '1' from Receivable r with(nolock) where r.OrgId = c.OrgId and r.ReceivableNumber = c.ReceivableNumber) Order by c.ReceivableNumber desc
但在Azure数据库查询性能洞察中,发现资源消耗最高的是如下查询:
(@orgId bigint,@contractNumber nvarchar(12)) Select top 1 * From ReceivableCut c with (nolock) Where 1=1 And c.ReceivableCutIndicator = 0 And c.OrgId = @orgId And c.ContractNumber = @contractNumber And exists (select '1' from Receivable r with(nolock) where r.OrgId = c.OrgId and r.ReceivableNumber = c.ReceivableNumber) Order by c.ReceivableNumber desc option (PLAN PER VALUE(ObjectID = 0, QueryVariantID = 3, predicate_range([DB_MERCHANTS_PAYMENT].[dbo].[ReceivableCut].[OrgId] = @orgId, 100.0, 1000000.0)))
该查询未在我的代码中定义,且执行次数与预期的原查询次数完全一致。我的ORM(EF Core)并未生成这条新查询,请问它来自何处?核心问题是@orgId始终为63,导致该提示完全错误!
分析与解答
- 带
option (PLAN PER VALUE...)的查询是Azure SQL数据库自动生成的,属于数据库层面的参数敏感性优化机制,和EF Core、应用代码无关。 - PLAN PER VALUE是Azure SQL针对参数化查询的优化特性:当数据库检测到同一参数化查询在不同参数值下执行效率差异极大时,会自动为不同参数范围生成专属执行计划,并通过该选项标记区分。
- 你遇到的核心问题是数据库误判了参数范围:它认为
@orgId的取值在100到1000000区间,但实际你的@orgId固定为63,不在该区间内,导致生成的执行计划完全不匹配,反而引发资源消耗过高。 - 可行的解决方向:
- 手动创建针对
@orgId=63的特定执行计划,强制数据库使用该计划; - 在EF Core生成的查询中添加
OPTION (USE HINT('DISABLE_PARAMETER_SENSITIVE_PLAN_OPTIMIZATION')),禁用该查询的参数敏感性优化; - 检查
ReceivableCut表的索引设计,确保OrgId、ContractNumber等过滤字段的索引足够高效,减少数据库误判的概率。
- 手动创建针对
内容的提问来源于stack exchange,提问作者Leonardo
相关产品推荐
相关产品推荐

