65

私は数百のテーブルを含む非常に大規模なデータベースを持っており、多くの製品をアップグレードした後、それらの半分はもう使用されていないと確信しています。テーブルがアクティブに選択されているかどうかを確認するにはどうすればよいですか?プロファイラーを使用することはできません。数日以上監視したいだけでなく、何千ものストアドプロシージャもあり、プロファイラーはSP呼び出しをテーブルアクセス呼び出しに変換しません。

私が考えることができる唯一のことは、対象のテーブルにクラスター化されたインデックスを作成し、クラスター化されたインデックスにsys.dm_db_index_usage_statsシークまたはスキャンがあるかどうかを監視することです。これは、テーブルからのデータがロードされたことを意味します。ただし、実際には実行可能ではないため、すべてのテーブルにクラスター化インデックスを追加することは(さまざまな理由で)悪い考えです。

他に選択肢はありますか?私は常に「SELECTトリガー」のような機能が必要でしたが、SQLServerにその機能がない理由はおそらく他にもあります。

解決:

レムス、私を正しい方向に向けてくれてありがとう。これらの列を使用して、次の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)
4

6 に答える 6

48

sys.dm_db_index_usage_statsを調べます。列last_user_xxxには、ユーザー要求からテーブルに最後にアクセスされた時刻が含まれます。このテーブルは、サーバーの再起動後に追跡をリセットするため、データに依存する前に、しばらく実行したままにしておく必要があります。

于 2010-01-28T16:19:36.090 に答える
6

Re:プロファイラー。SP:StmtCompletedを監視する場合、ストアドプロシージャ内で実行されているすべてのステートメントをキャプチャするため、sproc内のテーブルアクセスをキャッチします。すべてがストアドプロシージャを通過しない場合は、SQL:StmtCompletedイベントも必要になる場合があります。

多数のイベントが発生するため、トレースのサイズが原因で、長期間にわたってトレースすることはおそらくまだ実用的ではありません。ただし、フィルターを適用することはできます。たとえば、TextDataにチェックするテーブルの名前が含まれている場合です。一度にフィルタリングするテーブル名のリストを指定して、徐々に処理することができます。したがって、これらのテーブルのいずれにもアクセスされていない場合は、トレースイベントを取得しないでください。

それがあなたにとって適切で実行可能なアプローチではないと感じたとしても、私はそれを拡大する価値があると思いました。

別の解決策は、ソースコードのグローバル検索を実行して、テーブルへの参照を見つけることです。ストアドプロシージャの定義をクエリして、特定のテーブルの一致を確認するか、完全なデータベーススクリプトを生成して、テーブル名の検索を実行することができます。

于 2010-01-28T15:44:44.347 に答える
3

SQL Server 2008の場合は、SQL監査を確認する必要があります。これにより、テーブルの選択やファイルまたはイベントログへのレポートなど、多くのことを監査できます。

于 2010-01-28T15:35:07.233 に答える
1

次のクエリは、クエリプランキャッシュを使用して、キャッシュ内の既存のプランのいずれかにテーブルへの参照があるかどうかを確認します。これは100%正確であるとは限りません(メモリの制約がある場合はクエリプランがフラッシュされるため)が、テーブルの使用に関する洞察を得るために使用できます。

SELECT schema_name(schema_id) as schemaName, t.name as tableName,
    databases.name,
dm_exec_sql_text.text AS TSQL_Text,
dm_exec_query_stats.creation_time, 
dm_exec_query_stats.execution_count,
dm_exec_query_stats.total_worker_time AS total_cpu_time,
dm_exec_query_stats.total_elapsed_time, 
dm_exec_query_stats.total_logical_reads, 
dm_exec_query_stats.total_physical_reads, 
dm_exec_query_plan.query_plan
FROM sys.dm_exec_query_stats 
CROSS APPLY sys.dm_exec_sql_text(dm_exec_query_stats.plan_handle)
CROSS APPLY sys.dm_exec_query_plan(dm_exec_query_stats.plan_handle)
INNER JOIN sys.databases ON dm_exec_sql_text.dbid = databases.database_id
RIGHT JOIN sys.tables t (NOLOCK) ON cast(dm_exec_query_plan.query_plan as varchar(max)) like '%' + t.name + '%'
于 2019-05-21T18:08:35.360 に答える
0

さまざまなテーブルのユーザー権限で遊ぶことを念頭に置いていましたが、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;

/

次に、トレースファイルを確認できます。

于 2010-01-28T16:07:56.550 に答える
-1

この解決策は、上記の解決策よりもうまく機能します。ただし、サーバーも再起動されなかったという制限がありますが、使用されていないテーブルについては十分に理解できます。

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
于 2013-03-27T13:20:26.920 に答える