T-SQL:为什么在没有GO的情况下,在一个批处理中运行多个SQL语句的速度较慢



我遇到了一个非常有趣的问题(至少对我来说(。

当我运行以下SQL:时

SELECT count(*) AS [count]
FROM [dbo].[contract_v] AS [contract_v]
WHERE 1 = 0;
SELECT *
FROM [dbo].[contract] AS [contract]
LEFT JOIN ([dbo].[contract_accepted_garbage_type] AS [garbageTypes->contract_accepted_garbage_type]
INNER JOIN [dbo].[garbage_type] AS [garbageTypes] ON [garbageTypes].[id] = [garbageTypes->contract_accepted_garbage_type].[garbage_type_id]) 
ON [contract].[id] = [garbageTypes->contract_accepted_garbage_type].[contract_id]
WHERE [contract].[id] IN (125018);

执行需要21秒

然而,当我添加GO语句如下:

SELECT count(*) AS [count]
FROM [dbo].[contract_v] AS [contract_v]
WHERE 1 = 0;
GO
SELECT *
FROM [dbo].[contract] AS [contract]
LEFT JOIN ([dbo].[contract_accepted_garbage_type] AS [garbageTypes->contract_accepted_garbage_type]
INNER JOIN [dbo].[garbage_type] AS [garbageTypes] ON [garbageTypes].[id] = [garbageTypes->contract_accepted_garbage_type].[garbage_type_id])
ON [contract].[id] = [garbageTypes->contract_accepted_garbage_type].[contract_id]
WHERE [contract].[id] IN (125018);

只需要2秒。

第一条SQL语句中使用的视图基于第二条语句中调用的表。

你能向我解释一下这种行为吗?我知道GO语句使数据库为每个批创建单独的执行计划。我已经检查了执行计划,实际步骤是相同的。

谢谢!

GO关键字分隔执行批。如果两个查询中的基础表相同,并且它们在同一批中执行,那么两个查询都必须使用相同的事务上下文执行。这样可以确保两个表中的底层数据在两次执行过程中都是相同的。

如果使用单独的批处理(介于两者之间的GO语句(,则不能保证数据的一致性,因为理论上可以在执行之间修改行。

如果您不关心数据在两次查询之间发生变化的可能性,那么一定要使用GO来提高性能。如果你真的在乎,那就认为这是一个危险的举动。

SQL Server应用程序可以将多个Transact-SQL语句发送到SQL Server实例,以便作为批处理执行。然后将批处理中的语句编译为单个执行计划。在SQL Server实用程序中执行特别语句,或构建Transact-SQL语句的脚本以在SQL Server应用程序中运行的程序员,使用GO来发出批处理结束的信号。

https://learn.microsoft.com/en-us/sql/t-sql/language-elements/sql-server-utilities-statements-go?view=sql-服务器-ver15

相关内容

最新更新