Entity Framework Core 8Where IN 与Where IN OPENJSON

问题描述 投票:0回答:1

EF Core 8 现在使用

WHERE IN
OPENJSON
的组合在 where 语句中内联值,而不是之前的
WHERE IN(...)

此更改已在文档中注明,说明的原因如下:

这里的值内联是通过这样一种方式完成的: SQL注入攻击的可能性。描述了使用 JSON 的更改 以下都是关于性能的,与安全无关。

不幸的是,

OPENJSON
我们 2017 年 SQL Server 实例的性能很差。

下面的查询由 EF Core 8 生成,运行需要 1.8 秒,并导致近 400,000 次读取

DECLARE @__scheduleTagIds_0 nvarchar(4000) = N'[5835,5970,6563,6564,6565,6645,6835,6850,7034,7127]';

SELECT  [s].[ScheduleTagId]
       ,[s].[MustStartProdBy]
FROM    [ScheduleTagMustStartBy] AS [s]
WHERE   [s].[ScheduleTagId] IN (
    SELECT  [s0].[value]
    FROM    OPENJSON(@__scheduleTagIds_0) WITH ([value] int '$') AS [s0]
)

如果我重构查询以使用标准

WHERE IN(...)
,执行时间将降至 120ms29,000 次读取

SELECT  [s].[ScheduleTagId]
       ,[s].[MustStartProdBy]
FROM    [ScheduleTagMustStartBy] AS [s]
WHERE   [s].[ScheduleTagId] IN (5835,5970,6563,6564,6565,6645,6835,6850,7034,7127)

我的应用程序中有数百个使用

.Where(x => [collection].Contains(x.Id))
的查询,我非常担心在选择查询中看到的性能下降。

问题

  1. 根据文档,防止使用
    OPENJSON(...
    的唯一方法是将数据库兼容性级别更改为 120(低于 SQL Server 2016)。这不是一个理想的解决方案。还有其他方法可以限制/阻止
    OPENJSON
    的使用吗?
  2. SQL Server 上是否存在可以提高
    OPENJSON
    性能的配置?从分析器数据中可以清楚地看出,SQL Server 在使用
    OPENJSON
    时无法正确使用索引。
c# entity-framework-core sql-server-2017 ef-core-8.0
1个回答
0
投票

根据文档,防止使用的唯一方法 OPENJSON(...是将DB兼容性级别更改为120(更低 比 SQL Server 2016)。这不是一个理想的解决方案。有没有 还有其他方法来限制/阻止 OPENJSON 的使用吗?

您不必将数据库兼容级别更改为 120。您可以调用

UseCompatibilityLevel(120)
来告诉 EF 生成旧式 SQL,无论兼容级别实际设置为什么。

还有一个选项可以避免这种全局设置,而只是恒定化有问题的特定查询。但我认为这还没有正式发布,所以你需要使用每日构建。

SQL Server 上是否有一些配置方面的东西可以 提高 OPENJSON 的性能?从分析器看来很清楚 SQL Server 在使用时无法正确使用索引的数据 开放 JSON。

它当然可以使用索引

OPENJSON
它只是可能选择不这样做。

当你传递常量时它可以确定

  • 您传递了多少物品?
  • 您传递了多少重复项?有的话吗?
  • 您传递的确切值是多少? (如果您的基数倾斜,这可能很有用)

对于

OPENJSON
,它无法说出任何内容,因此它只能退回到猜测。这可能会导致不同的(更糟糕的)计划。

© www.soinside.com 2019 - 2024. All rights reserved.