【发布时间】:2021-03-03 02:01:00
【问题描述】:
我遇到了一个非常有趣的问题(至少对我来说)。
当我运行以下 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不是 SQL 语句 - 它是一个 delimiter 用于例如SQL Server Mgmt Studio(以及sqlcmd等工具)用于分隔 批次的 SQL 语句。 -
您在两次尝试刷新缓存之间做了什么,...?您是否尝试以相反的顺序运行
GO/noGO示例?对性能进行基准测试时的一个常见问题是,第一个操作将表、索引等加载到内存中,而当第二个查询运行时它仍然存在,从而节省了物理读取。 -
@HABO 我已经尝试过各种组合,每次没有 GO 的情况都会变慢,当我多次运行没有 GO 的语句时,每次需要 20 秒。看来数据库缓存与这个性能问题无关。
标签: performance tsql