目前我正在使用MSSQL服务器(2008R2或2012),我想询问在一个程序中放入多个DML语句是否会导致性能下降(丢弃)?
据我所知,这里的经验法则是将每个DML语句放入单独的存储过程中,并从一个包装程序中调用它们。
根据我所说的,使性能变差的事实是,当多个DML在一个过程中时,不能创建和存储该过程的良好执行计划。另一方面,当DML在自己的程序中分开时,每个人都会制定适当的执行计划。
最后值得一提的是,我将把所有DML包装在一个显式事务中 - 无论是在一个程序中还是在单独的程序中。
一个程序中的多个DML语句确实存在很大问题吗?
感谢。
答案 0 :(得分:3)
你问,因为你所说的不是真的。无论是在单个存储过程中还是在展开过程中,多个DML语句仅在通过显式BEGIN TRAN和COMMIT / ROLLBACK明确分组时才会相互影响。你应该将逻辑放在最有意义的地方(意思是,它最容易理解,最易读,可维护)。
此外,如果单个proc要调用多个proc,那么在单个proc和多个proc中将它们放在概念上真正的区别是什么?当单个proc调用多个proc并且每个都有DML语句时,当将多个DML语句放入单个proc时,这个存储过程的理论属性是否会使事情变得更糟?最后,您仍然只有一个入口点负责多个DML调用。
例如:
INSERT ....
DELETE ....
是两个单独的事务,因为每个查询本身都是一个事务(除非在显式事务中分组)。那么:
BEGIN TRAN
INSERT ....
DELETE ....
COMMIT TRAN
是单笔交易。由于并发(即阻塞/死锁),在事务中有多个DML语句会出现性能问题,但如果操作要求两个DML语句在概念上都是一个原子工作单元,那么它们需要在显式交易中组合在一起。
现在,鉴于上面的第一个例子有两个DML语句而没有显式事务,假设它们存在于存储过程中,那就没有什么不同了:
CREATE PROC MasterProc
AS
EXEC SubProc1;
EXEC SubProc2;
GO
CREATE PROC SubProc1
AS
INSERT ...
GO
CREATE PROC SubProc2
AS
DELETE ...
GO
并且,给出第二个示例,其中两个DML语句在显式事务中分组,假设它们在存储过程中,这与(使用与上述相同的两个SubProc *过程)没有区别:
CREATE PROC MasterProc
AS
BEGIN TRAN;
EXEC SubProc1;
EXEC SubProc2;
COMMIT TRAN;
GO
修改强>
一些额外的信息显然是单个存储过程中的多个DML语句对性能更差的原因是(假设)SQL Server无法获得正确的" (即好?)组合的执行计划,但如果DML语句是分开的,那么SQL Server可以生成"适当的" (即好?)每个单独的存储过程的执行计划。
嗯,执行计划确实处于查询级别。当然,在SQL Server 2000之前,只能重新编译整个过程,但从SQL Server 2005开始,可以进行语句级重新编译。但无论哪种方式,每个查询都会自行优化,因此将它们分开并不能提供任何好处。事实上,鉴于局部变量(包括表变量)不能在存储过程中共享,如果必须将每个变量作为输入传递,它肯定会使您在特定存储过程中尝试完成的内容复杂化param并将其中一个或多个传回。该代码很难维护和调试。
编辑2:
以下是一些资源,其中包含有关执行计划缓存和重新编译的信息:
[ ({ plan_handle | sql_handle | pool_name }) ]
删除单个计划)请注意,这些文档确实是指在对象(即存储过程等)级别缓存的执行计划。但是,这并不意味着DML语句作为一个整体进行了优化,如果分离出来则会有所不同。将DML语句分离为单独的存储过程的唯一真正好处是,您可以(从SQL Server 2008开始)通过DBCC FREEPROCCACHE ({ plan_handle | sql_handle })
单独手动发出重新编译请求。但是,如果这只是偶尔需要的东西,那么重新编译整个存储过程就不会真正受到伤害,与笨重的代码分离相比,这可能不是一个成本。并且,如果它经常需要,那么DML语句本身可以添加OPTION (RECOMPILE)
,但不会影响该存储过程中的其他查询。
编辑3:(希望最终:) 让我们不要忘记,这仍然是我们正在做的计算机 Science ,而且几乎所有东西都是可测试的。设置一个带有表和几个过程的场景(如上面显示的例子)并运行" master"这应该相当容易。 proc调用子存储过程以及all-in-one proc。您可以查看"实际执行计划"在SSMS中运行它们或从计划缓存中提取计划(如上面的链接资源所示)。所以在技术上,没有人需要依赖这个神秘的人,他建议使用单独的存储过程,甚至是那些认为这个想法最好是过时的,最糟糕的纯粹神话的人; SQL Server会告诉您完全在任何给定情况下它将做什么:)。