SQL Server 2014-内存泄漏和巨大的CPU使用用户定义的函数内的变量
问题描述:
我有一个SQL Server 2014的实例。到主数据库中,我创建了一些用户定义的函数,以便简化使用期间的查询。 NET应用程序。SQL Server 2014-内存泄漏和巨大的CPU使用用户定义的函数内的变量
我在特定函数中遇到了内存和性能问题。这是我正在使用的功能:
ALTER FUNCTION [dbo].[getNotificationInspections](
@range int = 3
)
RETURNS
@Notifies TABLE
(
min_id_history int,
max_id_history int,
disCounter tinyint,
name_job varchar(15),
desc_job varchar(150),
id_inspect smallint,
pc_host varchar(15),
name_inspect varchar(10),
link_image varchar(100)
)
AS
BEGIN
DECLARE @minHistory int
DECLARE @maxHistory int
SELECT @minHistory = minHistory,
@maxHistory = maxHistory
FROM getLastEngineRange(@range)
--SELECT @minHistory, @macHistory
INSERT @Notifies
SELECT @minHistory min_id_history, @macHistory max_id_history, DS.*
FROM dbo.RealDiscardRange(@minHistory, @maxHistory) DS
WHERE DS.disCounter = @range
RETURN
END
此功能工作正常,除了它需要约4-5秒和约1.5Gb的内存! 3排!但让我们继续看看发生了什么。
如果我执行定义@maxHistory唯一的查询和@minHistory它不使用CPU或时间或内存。
如果我使用“使用的值,而不是变量”的INSERT @Notifies查询它花费200ms左右,无记忆!
因此,在查询中使用变量需要巨大的CPU和内存!
事实上,如果我用这个查询出来的功能,但作为一个简单的查询:
INSERT @Notifies
EXEC('SELECT min_id_history=''' + @minHistory + ''',
max_id_history=''' + @maxHistory + ''', DS.*
FROM dbo.RealDiscardRange(' + @minHistory + ', ' + @maxHistory + ') DS
WHERE DS.disCounter = ' + @range + ' ')
RETURN
的时间和内存spended执行这个人是可以忽略不计。每次SQL Server服务时都会重新启动这些测试。
我希望有人能解释这一点。
答
[1]我并不是说SQL Server不具备这样的错误(如某处内存泄漏),但99.999%,我觉得这是不是这样的。给出我没有其他信息的事实,对于某些运营商从执行计划中生成的行数,它似乎只是一个错误的估计(高估)。
上述[2]的源代码不编译的:不是
SELECT ..., @macHistory max_id_history, ...
应该是
SELECT ..., @maxHistory max_id_history, ...
[3]代替多步TVF的我将因此测试一个内联函数:
ALTER FUNCTION [dbo].[getNotificationInspections](
@range int = 3
)
RETURNS TABLE
AS
RETURN
SELECT min_id_history = f1.minHistory,
max_id_history = f1.maxHistory,
disCounter = ds.disCounter,
name_job = ds.name_job,
desc_job = ds.desc_job,
id_inspect = ds.id_inspect,
pc_host = ds.pc_host,
name_inspect = ds.name_inspect,
link_image = ds.link_image
FROM dbo.getLastEngineRange(@range) f1
CROSS APPLY dbo.RealDiscardRange(f1.minHistory, f1.maxHistory) ds
WHERE ds.disCounter = @range;
GO
原因是,大多数时候,内联TVFs执行多步相比,因为TVFs多级较好查询优化器就像一个黑盒子。相反,内联TVF只不过是一个带参数的视图,对于每个内联TVF调用,SQL Server将源代码扩展到主查询(调用者)源代码中,然后优化所有源代码(作为all)。
[4]如果没有帮助,那么你应该公布执行计划(也许这是更好地在任何情况下,发布此XP)。
我认为,它与你的问题中的错字没有关系?你在返回的SELECT语句中有macHistory而不是maxHistory? –
最有可能是次优执行计划而不是内存泄漏。 SQL Server缓存数据,直到检测到内存压力时才释放内存。不理想的计划会触及更多的数据,并因此使用更多缓存。 –
你如何测量内存消耗?请发布执行计划。 –