如何在SQL中检查数据库以确保其所有表都在使用中?

时间:2018-12-20 20:39:52

标签: sql-server

我被分配去查看是否使用了数据库中的所有当前表,以及是否不删除它们。这些是我到目前为止已采取的步骤:

  1. 在使用该数据库的程序中搜索表名,以查看是否已基于这些表名在程序中进行了查询。

  2. 研究是否在其他任何地方(例如视图或表)使用了表主键(与其他使用的表的连接性)。我用过:

    SELECT 
        t.name AS table_name, 
        SCHEMA_NAME(schema_id) AS schema_name, 
        c.name AS column_name 
    FROM 
        sys.tables AS t 
    INNER JOIN 
        sys.columns c ON t.OBJECT_ID = c.OBJECT_ID 
    WHERE 
        c.name LIKE 'DeflectionId' -- write the column you search here 
    ORDER BY 
        schema_name, table_name; 
    
  3. 在所有存储过程文本中进行搜索,以查看其中是否使用了表名:

    SELECT DISTINCT
        o.name AS Object_Name,
        o.type_desc
    FROM  
        sys.sql_modules m
    INNER JOIN
        sys.objects o ON m.object_id = o.object_id
    WHERE 
        m.definition LIKE '%\[Test_Results_LU\]%' ESCAPE '\';
    

    SELECT name
    FROM sys.procedures
    WHERE Object_definition(object_id) LIKE '%Test_Results_LU%'
    

    (通过此链接:Search text in stored procedure in SQL Server

  4. 使用对象资源管理器视图查看数据库中是否存在具有相似/相同名称和大小的表。

您认为我还有其他方法可以用来对其进行更好的调查吗?

这些步骤有效吗?你会怎么做?

2 个答案:

答案 0 :(得分:3)

所有这些都是合理的检查对象。要做的另一件事是根据您的SQL Server版本打开概要分析或审核,并实际上监视在合理时间段内使用的表。您可能无法使用生产系统来做到这一点,而且仍然无法100%保证-如果有一个重要的表每年只查询一次,该怎么办?

https://dba.stackexchange.com/questions/40960/logging-queries-and-other-t-sql https://docs.microsoft.com/en-us/sql/relational-databases/security/auditing/view-a-sql-server-audit-log?view=sql-server-2017

删除表之前的另一个建议是显式删除对它们的访问(使用DENY / REVOKE或将它们重命名为table-name_purge)一两个星期,看看是否有人抱怨。如果没有,那么备份并丢弃它们可能是安全的。

答案 1 :(得分:2)

另外两个地方需要检查。这些都依赖于

  • 由系统自动缓存
  • 两次重启之间不持久
  • 可以随时删除。

因此,从这些结果中得出的不存在并不表示该表未被使用,但是您可能会发现有证据表明该表确实在使用中。

SELECT [Schema] = OBJECT_SCHEMA_NAME(object_id), 
       [ObjectName] = OBJECT_NAME(object_id),
       *
FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID()

在计划缓存中

USE YourDB

DROP TABLE IF EXISTS #cached_plans, #plans, #results

DECLARE @dbname nvarchar(300) = QUOTENAME(DB_NAME());


SELECT dm_exec_query_stats.creation_time,                               
       dm_exec_query_stats.last_execution_time,                             
       dm_exec_query_stats.execution_count,                             
       dm_exec_query_stats.sql_handle,                              
       dm_exec_query_stats.plan_handle                              
INTO   #cached_plans                                
FROM   sys.dm_exec_query_stats;                             

WITH distinctph                             
     AS (SELECT DISTINCT plan_handle                                
         FROM   #cached_plans)                              
SELECT query_plan,                              
       plan_handle                              
INTO   #plans                               
FROM   distinctph                               
       CROSS APPLY sys.dm_exec_query_plan(plan_handle);                             

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')                              
SELECT      cp.*,                               
            st.text,
            [Database] = n.value('@Database', 'nvarchar(300)'),
            [Schema] = n.value('@Schema', 'nvarchar(300)'),
            [Table] = n.value('@Table', 'nvarchar(300)')                            
INTO        #results                                
FROM        #cached_plans cp                                
JOIN        #plans p                                
ON          cp.plan_handle = p.plan_handle                              
CROSS APPLY sys.dm_exec_sql_text(sql_handle) st 
CROSS APPLY query_plan.nodes('//Object[@Database = sql:variable("@dbname") and @Schema != "[sys]"]') qn(n);

SELECT *
FROM #results