TOP
我不想使用time 来限制查询返回的行数。
我试图通过DATEDIFF
and来实现这一点SYSDATETIME
:
DECLARE @Start DATETIME2(7) = SYSDATETIME()
SELECT *
FROM [MyTable]
WHERE DATEDIFF(SECOND, @Start, SYSDATETIME()) <= 1
但实际上这超出了时间限制并返回表中的每一行。
谁能提出更好的方法?
上下文:我一直在寻找一种在各种重复更新任务之间平均共享系统资源的方法,其中一些任务比其他任务占用更多资源(通常受 CPU 限制)。我实际上已经以不同的方式解决了这个问题,但我仍然很想知道有什么可能。我正在使用 SQL Server 2022 Express Edition。
简短的回答是:不。
这不可能。
做这样的事情是不可能的,不。
即使这样做是合理的,但它仍然是荒谬的原因如下:执行查询时发生的第一件事是 SQL 引擎提出执行计划,这是一系列操作它计划执行以处理查询。该执行计划中包括向服务器请求 SQL 引擎认为处理该执行计划所需的资源。然后服务器授予它合理的资源,以尝试满足该请求。
甚至在查询返回一行之前,内存就已经被授予和保留用于为该查询提供服务。默认情况下,服务器上可授予单个查询的内存的最大限制为 25% 。(是的,对于一个查询来说很多。)因此,即使您可以为特定查询实施查询超时,它也不会实现您的实际目标 - 改进硬件资源共享。
相反,实现这一目标的最佳方法是了解您的查询在做什么。阅读执行计划本身就是一个很好的方法。调整查询中的任何重大瓶颈 - 有时可能涉及索引调整、重写查询本身,或者在更极端的情况下重新构建整个过程和/或数据库设计,这些都是改善服务器资源的方法。
对于某些场景,调整正在处理的记录的批次大小(通过 a
TOP
或什至更好地通过适用的谓词来更早地过滤数据集)并且有时采用迭代方法来处理所有批次有助于让服务器呼吸更多。但是在实施这种方法之前,了解您是否真的有硬件争用问题是很重要的。您的想法行不通,因为“当前时间”函数在语句的持续时间内
SYSDATETIME
被视为运行时常量。在语句开始执行之前记录单个值,每次计算函数时都会使用缓存值。即使它确实按照您希望的方式工作,SQL Server 也会继续测试表中每一行的谓词,而不是在时间限制结束时停止。
SQL Server 不提供在指定时间后以概念上类似于
SET LOCK_TIMEOUT
.一些客户端确实提供超时功能,但那些通常只是在适当的时候向服务器发送“取消”命令(注意信号)。
出于好奇,您可以做一些可怕且低效的事情,例如:
这会引发“遇到零错误除法”错误,但我鼓励您重新考虑整个事情。它无论如何都不可靠,因为 SQL Server 不保证表达式计算的次数或时间。它恰好适用于简单的案例。
您还可以创建一个标量函数(呃!)来在每次调用时返回当前时间,但这样效率更低。
有许多创造性的糟糕方法可以尝试这一点。抵抗!