虽然听起来很奇怪,但我需要减慢 SQL 查询的速度。目前,我在内部开发服务器上使用 Microsoft SQL Server 2008 R2 和 AdventureWorks 数据库。我正在测试一些代码,无论我尝试什么,我运行的查询都太快了!
基本上我正在测试一个切断功能,并且需要足够长的查询才能在完成之前切断它。
不幸的是,由于它是本地安装,AdventureWorks 数据库中没有单个查询或足够大的表来真正为我提供良好的数据来使用。我试过了
WAITFOR DELAY '01:00'
这非常适合测试以确保它正常工作,但现在我需要测试看看是否可以在读取过程中切断数据流。 WAITFOR 语句在这方面对我来说并不公平,因为我需要它主动从服务器检索数据。我的第一直觉是使用复杂的计算来减慢速度,但是即使让 SQL Server 将查询中的所有数值乘以 37 倍也只会减慢查询的毫秒数。我尝试的第二件事是将
WAITFOR
语句嵌入子查询中,但看来你不能这样做。最后,我唯一没有尝试过的是执行多个存储过程以及它们之间的WAITFOR
,但我认为这不能满足我的需要。
我不得不说,当你离服务器这么近时,做出一个绝对糟糕的查询是多么困难,这给我留下了深刻的印象。
有什么方法可以轻松减慢查询速度吗?
谢谢!
只需进行大量交叉连接即可。
SELECT T1.*
FROM SomeTable T1,
SomeTable T2,
SomeTable T3,
SomeTable T4
对于将生成 10,000 亿行的 1,000 行表,这应该足够慢了。
DECLARE @EndTime DATETIME;
SET @EndTime = DATEADD(s, 5, GETDATE()); -- Set your delay here
WHILE @EndTime > GETDATE()
SELECT 'Test Result'; -- Add your desired query here
编辑
使用递归的另一个选项:
为
GETDATE()
创建 UDF 包装器,以便为结果中的每一行计算新的日期值:
CREATE FUNCTION dbo.GetExactDate()
RETURNS DATETIME
AS
BEGIN
RETURN GETDATE();
END
然后使用cte
DECLARE @EndTime DATETIME;
SET @EndTime = DATEADD(s, 5, GETDATE()); -- Set your delay here
WITH cte AS (
SELECT dbo.GetExactDate() Value
UNION ALL
SELECT dbo.GetExactDate()
FROM cte
WHERE Value < @EndTime
)
SELECT Value
FROM cte
OPTION (MAXRECURSION 0);
这样做的优点是在一个查询中返回结果,而不是很多(就像我的第一个解决方案),同时仍然能够设置您希望查询继续返回结果的时间。
在 SQL Server 2016 上测试:(SQL 视图查询总是需要两秒的时间来回复)
/* Call WAITFOR DELAY inside SQL View */
/* Usefull for example for async testing */
CREATE FUNCTION WaitForDelay()
RETURNS INT
AS
BEGIN
RETURN (
SELECT Value FROM OPENROWSET (
'SQLOLEDB', 'Trusted_Connection=yes; Integrated Security=SSPI; Server=localhost; Initial_Catalog=master;',
'WAITFOR DELAY ''00:00:02'' SELECT 0 AS Value'
))
END
GO
CREATE VIEW Wait AS
SELECT dbo.WaitForDelay() AS Value
GO
SELECT * FROM Wait /* Takes sql view 2 seconds to respond */
显示 Management Studio 执行简单视图故意减慢至 2 秒:
尽可能简单地使用
SELECT SLEEP(n);
,其中 n 是以秒为单位的时间。
这是一个很好的解决方案。
CREATE OR ALTER FUNCTION [dbo].[Sleep](@seconds INT)
RETURNS INT AS
BEGIN
DECLARE @startTime DATETIME2(7) = SYSDATETIME();
DECLARE @endTime DATETIME2(7) = DATEADD(SECOND, @seconds, @startTime);
WHILE (SYSDATETIME() < @endTime)
SET @startTime = @startTime;
RETURN @seconds;
END
GO
CREATE OR ALTER VIEW dbo.SlowView AS
SELECT
[dbo].[Sleep](5) AS DELAY,
NEWID() AS VALUE
GO
SELECT * FROM SlowView