临时表还是永久表?

5

我正在重新设计我的公司一些存储过程。原始的存储过程使用了大量永久性表,这些表在执行过程中被填充,在最后,这些值被删除。行数可以从100到50000行,用于计算聚合。

我的问题是,如果我用临时表替换那些永久性表,会有严重的性能问题吗?使用临时表是可行的吗?

7个回答

1

这取决于你使用它们的频率,处理所需的时间以及在写入时是否同时访问表中的数据。

如果您使用临时表,则在不使用时它不会等待索引和缓存。因此,在这里应该节省一点资源。但是,您将在临时表上产生开销(即创建和销毁)。

我建议重新检查过程中查询的功能,并考虑使用更多的过程内游标操作,而不是将所有内容加载到表中并删除它们。

然而,数据库用于存储信息和检索信息。我会避免将永久表用于常规临时工作,并坚持使用临时表。

总体性能不应对您在问题中指定的用例产生任何影响。

希望这可以帮助您,

Jeffrey Kevin Pry


我认为在回答这个问题之前,我需要看一下查询执行计划。 - harrisunderwork
@harrisunderwork:如果只有100-50,000行,那么即使只有50,000行,它真的不应该对性能造成重大影响。这只是我的个人看法... - Jeffrey Kevin Pry
这只是一个粗略的估计,不是每次都会有5万行,它们可能会增加或减少,这取决于查询类型。 - harrisunderwork

0

我同意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

1
同意,表变量通常是更好的选择。另一方面,存储过程可以访问在调用存储过程之前创建的临时表,而使用表变量则无法实现这一点。 - Andriy M
@Andriy M:是的,你说得对。这总是取决于你在数据上进行的哪种详细说明以及你的数据集有多大。在这里最好的方法是尝试不同的解决方案,并找到更快且使用更少资源的最佳方案。 - LeftyX

0

是的,这肯定是可行的,您可能需要检查永久表是否有任何索引以加快连接等操作。


0
一个重要的问题是,是否可以同时运行多个人的存储过程?我经常看到这些表从旧的单用户数据库中继承而来(或者从那些无法执行子查询或者除了SELECT * FROM之外的任何操作的程序员那里继承而来)。如果有多个用户尝试运行同一个过程会发生什么?如果在中途崩溃会发生什么-表会被清理吗?使用临时表或表变量,您可以将表正确地限定为当前连接。

这些表具有外键,根据特定用户访问它们进行映射。同样,只能使用这些键删除条目。 - harrisunderwork

0

一定要使用临时表,特别是因为您已经提到它的目的是帮助计算和聚合。如果您在数据库模式中使用了一个表,所有这些工作都将被记录 - 写入、备份等等。使用临时表可以消除数据的开销,最终您可能并不关心。


0

实际上,你可以在最后删除临时表而不是删除行,这样可能会节省一些时间(你说你有多个用户,所以必须删除而不是截断)。删除是一个记录操作,可能会给过程增加相当多的时间。如果永久表已经被索引,那么创建临时表并对其进行索引。我敢打赌,除非你的临时数据库接近空间极限,否则你会看到性能提高。

表变量也可能起作用,但它们无法被索引,并且通常只对较小的数据集更快。因此,您可以尝试将临时表与表变量结合使用,对于需要索引的大型项目使用临时表,对于较小的项目使用表变量。

使用临时表和表变量的优点是,您可以保证一个用户的进程不会干扰另一个用户的进程。你说他们目前有一种方法来识别哪些记录,但只要使用永久表就会引入一个错误,从而破坏它。将永久表用于临时处理是一个非常冒险的选择。临时表和表变量永远无法看到其他人进程中的数据,因此作为选择更安全。


0

通常情况下,表变量是最好的选择。

如果有许多临时表被操作,SQL2K及以下版本可能会出现显著的性能瓶颈 - 问题在于系统表上的阻塞DDL。

Sql2005更好,但表变量完全避免了使用这些系统表的问题,因此可以在没有用户间锁定问题(除了与源数据相关的问题)的情况下执行。

然后问题就在于表变量仅在范围内持久存在,因此,如果确实需要处理大量需要重复处理并需要在(相对)长时间内持久存在的数据,则“静态”工作表实际上可能更快 - 它确实需要某种用户键和定期清理。真正的最后手段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接