我怎么知道一个数据库表是否被访问了? 想要像“select触发器”

我有一个非常大的数据库,有数百个表,经过许多产品升级,我确信其中有一半不再被使用。 我怎么知道一张桌子是否正在被选中呢? 我不能只使用Profiler – 我不仅需要观察超过几天,而且还有成千上万的存储过程,Profiler也不会将SP调用转换为表访问调用。

我唯一能想到的就是在感兴趣的表上创build一个聚集索引,然后监视sys.dm_db_index_usage_stats以查看聚集索引中是否有任何查找或扫描,这意味着表中的数据已被加载。 但是,在每张表上添加聚簇索引是一个坏主意(由于许多原因),因为这是不可行的。

我还有其他select吗? 我一直想要一个像“SELECT触发器”这样的function,但是SQL Server也可能没有这个function。

解:

谢谢,Remus,指着我走向正确的方向。 使用这些列,我创build了下面的SELECT,这正是我想要的。

  WITH LastActivity (ObjectID, LastAction) AS ( SELECT object_id AS TableName, last_user_seek as LastAction FROM sys.dm_db_index_usage_stats u WHERE database_id = db_id(db_name()) UNION SELECT object_id AS TableName, last_user_scan as LastAction FROM sys.dm_db_index_usage_stats u WHERE database_id = db_id(db_name()) UNION SELECT object_id AS TableName, last_user_lookup as LastAction FROM sys.dm_db_index_usage_stats u WHERE database_id = db_id(db_name()) ) SELECT OBJECT_NAME(so.object_id) AS TableName, MAX(la.LastAction) as LastSelect FROM sys.objects so LEFT JOIN LastActivity la on so.object_id = la.ObjectID WHERE so.type = 'U' AND so.object_id > 100 GROUP BY OBJECT_NAME(so.object_id) ORDER BY OBJECT_NAME(so.object_id) 

查看sys.dm_db_index_usage_stats 。 last_user_xxx列将包含上次从用户请求访问表的时间。 此表在服务器重新启动后重置其跟踪,因此在依赖其数据之前,您必须保持运行一段时间。

Re:Profiler,如果你监视SP:StmtCompleted ,它将捕获在一个存储过程中执行的所有语句,这样就可以捕获一个存储过程中的表访问。 如果不是所有内容都通过存储过程,则可能还需要SQL:StmtCompleted事件。

将会有大量的事件,所以由于跟踪的大小,很可能跟踪很长一段时间。 但是,您可以应用一个filter – 例如,在哪里TextData包含您要检查的表的名称。 你可以给出一个表名列表来过滤,并逐步完成。 所以如果这些表没有被访问,你不应该得到任何跟踪事件。

即使你觉得这不是一个合适的/可行的方法,我认为这是值得继续。

另一个解决scheme是对源代码进行全局search,以查找对表的引用。 您可以查询存储过程定义以检查给定表的匹配,也可以只生成一个完整的数据库脚本,然后对该表执行查找操作。

对于SQL Server 2008,你应该看看SQL审计 。 这允许您审核很多事情,包括在表上select并报告给文件或事件日志。

一个侧面说明:如果你的意图是要删除这些表,你可能不得不考虑将它强加给你的法律义务,以保持x年的数据。

我想要玩不同的表的用户权限,但我记得你可以打开一个ON LOGON触发器跟踪你可能会从中受益:

 CREATE OR REPLACE TRIGGER SYS.ON_LOGON_ALL AFTER LOGON ON DATABASE WHEN ( USER 'MAX' ) BEGIN EXECUTE IMMEDIATE 'ALTER SESSION SET SQL_TRACE TRUE'; --EXECUTE IMMEDIATE 'alter session set events ''10046 trace name context forever level 12'''; EXCEPTION WHEN OTHERS THEN NULL; END; / 

然后你可以检查你的跟踪文件。

上面的解决scheme,这个解决scheme对我更好。 但是,服务器还没有重新启动,但仍然有限,但仍然给你一个不使用表的好主意。

 SELECT [name] ,[object_id] ,[principal_id] ,[schema_id] ,[parent_object_id] ,[type] ,[type_desc] ,[create_date] ,[modify_date] ,[is_ms_shipped] ,[is_published] ,[is_schema_published] FROM [COMTrans].[sys].[all_objects] where object_id not in ( select object_id from sys.dm_db_index_usage_stats ) and type='U' order by name