如何判断是否正在访问数据库表?想要像"SELECT触发器"这样的东西

Sql*_*yan 58 sql-server database-design clustered-index sql-server-2008

我有一个包含数百个表的非常大的数据库,经过许多产品升级后,我确信其中一半不再使用了.如何判断是否正在从中选择一个表?我不能只使用Profiler - 我不仅要观看超过几天,而且还有数千个存储过程,并且探查器不会将SP调用转换为表访问调用.

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

我还有其他选择吗?我一直想要一个像"SELECT触发器"这样的功能,但是可能还有其他原因导致SQL Server没有这个功能.

解:

谢谢,Remus,指出我正确的方向.使用这些列,我创建了以下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)
Run Code Online (Sandbox Code Playgroud)

Rem*_*anu 42

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

  • 等等——这真像我想象的那么棒吗?我将做一些测试,但看来我可以监视表上的“HEAP”虚拟索引以进行任何搜索/扫描/查找,这准确地告诉我我想知道的内容。如果是这样的话,先生,你就是我的英雄。 (3认同)
  • 它会做您认为它会做的事情,甚至更多。您可以区分未使用的表(0 个堆或 1 个聚集索引)和从未使用过的非聚集索引,以便您可以丢弃不必要的非聚集索引。请记住,它会在服务器重新启动时重置(实际上,当数据库联机时,它会重置该数据库,详细信息......) (3认同)
  • 请记住,暂时不使用可能并不意味着没有用处.年度报告每年只能运行一次.支持其中一些不常见任务的表可能在其余时间内看不到很多动作(或任何动作). (3认同)

Ada*_*Dev 6

Re:Profiler,如果您监视SP:StmtCompleted,它将捕获在存储过程中执行的所有语句,以便捕获sproc中的表访问.如果不是所有内容都通过存储过程,您可能还需要SQL:StmtCompleted事件.

将会有大量事件,因此由于跟踪的大小,长时间跟踪可能仍然不实用.但是,您可以应用过滤器 - 例如,TextData包含您要检查的表的名称.您可以在任何时候提供要过滤的表名列表,并逐步完成它们.因此,如果没有访问过这些表,则不应该获取任何跟踪事件.

即使你认为这对你来说不合适/可行,我认为值得继续扩展.

另一种解决方案是对源代码进行全局搜索,以查找对表的引用.您可以查询存储过程定义以检查给定表的匹配项,或者只生成完整的数据库脚本并对表名执行查找.

  • +1源代码搜索.某些应用程序具有非常少使用的功能,这些功能可能永远不会被分析/审核捕获.唯一可以确定的方法是实际检查使用数据库的程序! (3认同)