我正在重新设计我的公司一些存储过程。原始的存储过程使用了大量永久性表,这些表在执行过程中被填充,在最后,这些值被删除。行数可以从100到50000行,用于计算聚合。
我的问题是,如果我用临时表替换那些永久性表,会有严重的性能问题吗?使用临时表是可行的吗?
我正在重新设计我的公司一些存储过程。原始的存储过程使用了大量永久性表,这些表在执行过程中被填充,在最后,这些值被删除。行数可以从100到50000行,用于计算聚合。
我的问题是,如果我用临时表替换那些永久性表,会有严重的性能问题吗?使用临时表是可行的吗?
这取决于你使用它们的频率,处理所需的时间以及在写入时是否同时访问表中的数据。
如果您使用临时表,则在不使用时它不会等待索引和缓存。因此,在这里应该节省一点资源。但是,您将在临时表上产生开销(即创建和销毁)。
我建议重新检查过程中查询的功能,并考虑使用更多的过程内游标操作,而不是将所有内容加载到表中并删除它们。
然而,数据库用于存储信息和检索信息。我会避免将永久表用于常规临时工作,并坚持使用临时表。
总体性能不应对您在问题中指定的用例产生任何影响。
希望这可以帮助您,
Jeffrey Kevin Pry
我同意Jeffrey的观点。这取决于具体情况。
既然你正在使用Sql Server 2008,你可以看一下表变量。
它们应该比临时表更轻便。
我会定义一个返回类似于表变量的用户自定义函数:
CREATE FUNCTION .ufd_GetUsers ( @UserCode INT )
RETURNS @UsersTemp TABLE
(
UserCode INT NOT NULL,
RoleCode INT NOT NULL
)
AS
BEGIN
INSERT @RolesTemp
SELECT
dbo.UsersRoles.Code, Roles.Code
FROM
dbo.UsersRoles
INNER JOIN
dbo.UsersRolesRelations ON dbo.UsersRoles.Code = dbo.UsersRolesRelations.UserCode
INNER JOIN
dbo.UsersRoles Roles ON dbo.UsersRolesRelations.RoleCode = Roles.Code
WHERE dbo.UsersRoles.Code = @UserCode
INSERT @UsersTemp VALUES(@UserCode, @UserCode)
RETURN
END
是的,这肯定是可行的,您可能需要检查永久表是否有任何索引以加快连接等操作。
一定要使用临时表,特别是因为您已经提到它的目的是帮助计算和聚合。如果您在数据库模式中使用了一个表,所有这些工作都将被记录 - 写入、备份等等。使用临时表可以消除数据的开销,最终您可能并不关心。
实际上,你可以在最后删除临时表而不是删除行,这样可能会节省一些时间(你说你有多个用户,所以必须删除而不是截断)。删除是一个记录操作,可能会给过程增加相当多的时间。如果永久表已经被索引,那么创建临时表并对其进行索引。我敢打赌,除非你的临时数据库接近空间极限,否则你会看到性能提高。
表变量也可能起作用,但它们无法被索引,并且通常只对较小的数据集更快。因此,您可以尝试将临时表与表变量结合使用,对于需要索引的大型项目使用临时表,对于较小的项目使用表变量。
使用临时表和表变量的优点是,您可以保证一个用户的进程不会干扰另一个用户的进程。你说他们目前有一种方法来识别哪些记录,但只要使用永久表就会引入一个错误,从而破坏它。将永久表用于临时处理是一个非常冒险的选择。临时表和表变量永远无法看到其他人进程中的数据,因此作为选择更安全。
通常情况下,表变量是最好的选择。
如果有许多临时表被操作,SQL2K及以下版本可能会出现显著的性能瓶颈 - 问题在于系统表上的阻塞DDL。
Sql2005更好,但表变量完全避免了使用这些系统表的问题,因此可以在没有用户间锁定问题(除了与源数据相关的问题)的情况下执行。
然后问题就在于表变量仅在范围内持久存在,因此,如果确实需要处理大量需要重复处理并需要在(相对)长时间内持久存在的数据,则“静态”工作表实际上可能更快 - 它确实需要某种用户键和定期清理。真正的最后手段。