MSSQL数据库清理 - 如何找到未使用的对象(表,视图,过程,函数)

时间:2009-01-02 17:20:10

标签: sql-server logging

假设您已经继承了MS SQL 2000或2005数据库,并且您知道某些表,视图,过程和函数实际上并未在最终产品中使用。

是否有某种内部日志记录或其他机制可以告诉我哪些对象没有被调用?或者只被称为几次而不是数千次。

3 个答案:

答案 0 :(得分:7)

答案 1 :(得分:4)

答案将取决于数据库如何组合在一起,但我对类似问题的处理方法有3倍:

找出哪些对象没有内部依赖关系。您可以通过针对sysdepends的查询来解决此问题,例如:

select 
    id, 
    name
from
    sys.sysdepends sd
inner join sys.sysobjects so
    on so.id = sd.id
where 
    not exists (
        select 
            1
        from 
            sysdepends sd2
        where 
            sd2.depid = so.id
    )

您应该将此与收集对象类型(sysobjects.xtype)结合使用,因为您只想隔离表,函数,存储过程和视图。还要忽略任何以“sp_”开头的过程,除非人们一直在为你的应用程序创建带有这些名称的过程!

许多返回的程序可能是您的应用程序的入口点。也就是说,从您的应用程序层或其他远程调用中调用的过程,并且在数据库中没有任何依赖于它们的对象。

假设该过程不会过于侵入(它会产生一些额外的负载,但不会太多),您现在可以开启一些SP的分析:启动,SQL:BatchStarting和/或SP:StmtStarting事件。只要你认为合适,就运行它,理想情况下登录到sql表以便于交叉引用。您应该能够消除许多直接从您的应用程序调用的过程。

通过交叉引用此日志和您的从属对象列表中的文本数据,您希望可以隔离大部分未使用的过程。

最后,您可能希望获取此过程产生的候选列表,并针对它们grep您的源代码库。这是一项繁琐的任务,只是因为您在代码中找到引用并不意味着您需要它们!可能只是代码尚未被删除,尽管它现在在逻辑上是不可访问的。

这远非一个完美的过程。一个相对干净的选择是在服务器上设置更详细(因此是侵入性)的分析以监视所有活动。这可以包括在日志处于活动状态期间调用的每个SQL语句。然后,您可以从此文本数据中回溯依赖表甚至跨数据库依赖项。我发现了日志细节的可靠性(每秒尝试解析的行数太多)以及难以处理的数据的绝对数量。如果您的应用程序不太可能受此影响,那么这可能是一个很好的方法。

警告:

因为,据我所知,没有一个完美的答案,特别警惕删除表格。如果出现问题,可以轻松替换程序,功能和视图(尽管在刻录之前确保将它们放在源代码管理中!)。如果您感到非常紧张,为什么不重命名表并创建一个旧名称的视图,那么您就可以轻松了解。

答案 2 :(得分:3)

我们还可以使用以下查询查找未使用的列和表。我累了写光标。光标将为每个表的每列提供信息。

declare @name varchar(200), @id bigint, @columnname varchar(500)
declare @temptable table
(
 table_name varchar(500),
 Status bit
)
declare @temp_column_name table 
(
 table_name varchar(500),
 column_name varchar(500),
 Status bit
)


declare find_table_dependency cursor for
select name, id from sysobjects where xtype ='U'
open find_table_dependency
fetch find_table_dependency into @name, @id
while @@fetch_Status = 0
begin

 if exists(select top 1 name from sysobjects where id in 
   (select id from syscomments where text like '%'+@name +'%'))
  insert into @temptable
  select @name, 1
 else 
  insert into @temptable
  select @name, 0

 declare find_column_dependency cursor for
    select name from syscolumns where id = @id
 open find_column_dependency
 fetch find_column_dependency into @columnname
 while @@fetch_Status = 0
 begin

  if exists(select top 1 name from sysobjects where id in 
   (select id from syscomments where text like '%'+@columnname +'%'))
   insert into @temp_column_name
   select @name,@columnname, 1
  else 
   insert into @temp_column_name
   select @name,@columnname, 0

  fetch find_column_dependency into @columnname
 end
 close find_column_dependency
 deallocate find_column_dependency


 fetch find_table_dependency into @name, @id
end
close find_table_dependency
deallocate find_table_dependency

select * from @temptable
select * from @temp_column_name