Как я могу узнать, обращаются ли к таблице базы данных больше? Хотите что-то вроде «ВЫБРАТЬ триггер» - PullRequest
56 голосов
/ 28 января 2010

У меня очень большая база данных с сотнями таблиц, и после многих, многих обновлений продуктов, я уверен, что половина из них больше не используется. Как я могу узнать, активно ли выбирается таблица? Я не могу просто использовать Профилировщик - я не только хочу наблюдать более нескольких дней, но также существуют тысячи хранимых процедур, и профилировщик не будет переводить вызовы SP в вызовы доступа к таблице.

Единственное, о чем я могу думать, - это создать кластеризованный индекс для интересующих таблиц, а затем отслеживать sys.dm_db_index_usage_stats, чтобы увидеть, есть ли какие-либо поиски или сканирования в кластерном индексе, то есть данные из таблицы загружен. Однако добавление кластеризованного индекса в каждую таблицу является плохой идеей (по ряду причин), поскольку на самом деле это неосуществимо.

Есть ли у меня другие варианты? Я всегда хотел использовать такую ​​функцию, как «триггер SELECT», но, возможно, существуют и другие причины, по которым SQL Server также не имеет этой функции.

РЕШЕНИЕ:

Спасибо, Ремус, за то, что указал мне правильное направление. Используя эти столбцы, я создал следующий 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)

Ответы [ 7 ]

40 голосов
/ 28 января 2010

Загляните в sys.dm_db_index_usage_stats . Столбцы last_user_xxx будут содержать последний раз, когда к таблице обращались по запросам пользователей. Эта таблица сбрасывает свое отслеживание после перезапуска сервера, поэтому вы должны оставить его включенным на некоторое время, прежде чем полагаться на его данные.

6 голосов
/ 28 января 2010

Re: Профилировщик, если вы отслеживаете SP: StmtCompleted , который будет захватывать все операторы, выполняемые в рамках хранимой процедуры, так что будет перехватывать обращения к таблице внутри sproc. Если не все проходит через хранимые процедуры, вам также может понадобиться событие SQL: StmtCompleted .

Будет большое количество событий, поэтому, вероятно, все еще нецелесообразно отслеживать в течение длительного времени из-за размера трассировки. Тем не менее, вы можете применить фильтр - например, где TextData содержит имя вашей таблицы, которую вы хотите проверить. Вы можете дать список имен таблиц для фильтрации в любое время и постепенно прорабатывать их. Поэтому вы не должны получать никаких событий трассировки, если ни одна из этих таблиц не была открыта.

Даже если вы считаете, что этот подход вам не подходит, я подумал, что стоит продолжить.

Другим решением будет глобальный поиск вашего исходного кода для поиска ссылок на таблицы. Вы можете запросить определения хранимых процедур, чтобы проверить совпадения для данной таблицы, или просто сгенерировать полный скрипт базы данных и выполнить поиск по ним для имен таблиц.

3 голосов
/ 28 января 2010

Для SQL Server 2008 вы должны взглянуть на Аудит SQL . Это позволяет проверять многие вещи, включая выбор в таблице и отчеты в файл или журнал событий.

1 голос
/ 21 мая 2019

В следующем запросе используется кэш плана запроса, чтобы узнать, есть ли ссылка на таблицу в каком-либо из существующих планов в кеше. Это не гарантирует точности на 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 + '%'
0 голосов
/ 27 марта 2013

Это решение работает лучше для меня, чем решение выше. Но все еще ограничено тем, что сервер также не был перезапущен, но все же дает хорошее представление о таблицах, которые не используются.

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
0 голосов
/ 28 января 2010

Я имел в виду играть с правами доступа пользователей для разных столов, но потом вспомнил, что вы можете включить трассировку с помощью триггера 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;

/

Затем вы можете проверить файлы трассировки.

0 голосов
/ 28 января 2010

Дополнительное примечание: если вы намерены отказаться от этих таблиц, вам, возможно, придется рассмотреть юридические обязательства, которые налагают на вас обязательство сохранять данные в любом случае в течение x лет.

...