sql-server - SQL性能: does MSSQL optimise the use of date time functions or is it better to pass it as a parameter

标签 sql-server entity-framework datetime entity-framework-core query-optimization

我编写了这个相当简单的查询,其中根据名为 LastActivity 的 DateTimeOffset 列选择不到 5 分钟的记录。

我正在使用 EF,在检查实际查询时,我发现 EF 实际上转换了此条件: LastActivity > DateTimeOffset.UtcNow.AddMinutes(-5); 使用 SQL 日期时间函数进行查询:[s].[LastActivity] > DATEADD(min, CAST(-5.0E0 AS int) ), CAST(SYSUTCDATETIME() AS datetimeoffset))

正如您所看到的,它做了一些不必要的转换(例如 .AddMinutes 需要 double ),所以我想知道首先在代码中实际计算 DateTime 然后将结果作为查询传递给查询是否会更高效范围。 我知道这将取决于统计数据,但我还不能真正说出这些值将如何分布...... 我已经在示例数据库上运行了这两个查询,并且性能没有真正的差异,但是当数据集增加时,我认为这可能会改变。

我的问题是:当没有参数(但使用 DATEADD)时,SQL 将始终使用相同的查询计划,或者它会以某种方式优化它,因为我们使用的是 SYSUTCDATETIME,我的假设是否正确?

最佳答案

EF 为该查询提供的内容将正常工作,即使它的语法有点意外。

为什么?

  1. WHERE timestampcolumn > DATEADD(minute, number, something_meaning_now)sargeable过滤项:它可以使用 timestampcolumn 上的索引.
  2. SYSUTCDATETIME()是一个非确定性函数。这意味着 SQL Server 知道它的返回值基于除输入值之外的其他值。

所以,发生的事情是这样的:SQL Server 在使用日期之前“在代码中”计算日期,就像您在代码中所做的那样。因为 SQL Server 知道每次使用查询时计算的日期都会改变(因为它是不确定的),所以它的缓存执行计划不会将该日期绑定(bind)到常量,因此查询缓存不会膨胀。如果您的过滤器是timestampcolumn < DATEADD(minute, number, '2021-01-23 12:34'),它将被绑定(bind).

我已经在大规模生产中做过大量此类事情,并且工作正常。

您询问了有关扩大规模的问题。做到这一点的方法是将索引放在您的 s.LastActivity 上。柱子。但是,要弄清楚您需要哪些索引......

  1. 使用 SSMS
  2. 选择“显示实际查询计划”。
  3. 运行查询
  4. 查看查询计划。如果您需要的话,它会显示推荐的索引。

关于sql-server - SQL性能: does MSSQL optimise the use of date time functions or is it better to pass it as a parameter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66330408/

相关文章:

entity-framework - Entity Framework 包括集合/引用,其中

sql - 从 now() 函数中减去小时数

asp.net - 如何传递日期时间参数?

sql - 更新为 NULL 的列

sql - 查找具有相同的记录

c# - 使桌面客户端无需更新即可使用较新的 EF 数据库迁移

c# - 模型类属性字符串长度为 nvarchar max

java - 当确认更新行时,为什么我的PreparedStatement.executeUpdate 返回 0?

sql - T-SQL - 如何在字符串中搜索第 n 个字符

PHP 按日期排序数组?