确定数据库是否被使用或访问的最佳指标是什么?
我尝试了索引统计并基于 I/O 利用率,但似乎没有一个是好的指标。
问题:我在开发环境中有很多数据库,由于空间问题,我们正在尝试停用那些未使用的数据库,而不会真正弄乱真正需要的数据库。
SQL Server 并没有真正按照您想要的方式跟踪数据库访问,至少是向后跟踪(您可以设置诸如服务器端跟踪、扩展事件、审计等向前推进的内容)。
您可以使用一件事:跟踪索引使用情况和过程/触发器/查询统计信息的 DMV。例如:
;WITH d AS
(
SELECT d = database_id, name FROM sys.databases
WHERE state = 0 AND database_id BETWEEN 5 AND 32766
),
index_usage(d,lsk,lsc,llk,lupd) AS
(
SELECT database_id, MAX(last_user_seek), MAX(last_user_scan),
MAX(last_user_lookup), MAX(last_user_update)
FROM sys.dm_db_index_usage_stats
WHERE database_id BETWEEN 5 AND 32766
GROUP BY database_id
),
proc_stats(d,lproc) AS
(
SELECT database_id, MAX(last_execution_time)
FROM sys.dm_exec_procedure_stats
WHERE database_id BETWEEN 5 AND 32766
GROUP BY database_id
),
trig_stats(d,ltrig) AS
(
SELECT database_id, MAX(last_execution_time)
FROM sys.dm_exec_trigger_stats
WHERE database_id BETWEEN 5 AND 32766
GROUP BY database_id
),
query_stats(d,lquery) AS
(
SELECT t.[dbid], MAX(s.last_execution_time)
FROM sys.dm_exec_query_stats AS s
CROSS APPLY sys.dm_exec_sql_text(s.plan_handle) AS t
WHERE t.[dbid] BETWEEN 5 AND 32766
GROUP BY t.[dbid]
)
SELECT d.name,i.lsk,i.lsc,i.llk,i.lupd,p.lproc,t.ltrig,q.lquery
FROM d LEFT OUTER JOIN index_usage AS i ON d.d = i.d
LEFT OUTER JOIN proc_stats AS p ON d.d = p.d
LEFT OUTER JOIN trig_stats AS t ON d.d = t.d
LEFT OUTER JOIN query_stats AS q ON d.d = q.d;
Run Code Online (Sandbox Code Playgroud)
请注意,这些统计信息并不完全可靠,因为您可能没有任何存储过程,并且在其中找到的查询sys.dm_exec_query_stats
可能引用多个数据库,并且可能永远不会反映您所关心的数据库。
此外,它们会在 SQL Server 重新启动、数据库分离/附加或恢复或数据库自动关闭时重置,并且在某些情况下还可能依赖于仍在缓存中的计划(另一个数据库可以在几分钟内完全接管)。因此,如果您回顾过去,除非您知道在整个商业周期内这些事情都没有发生,否则我不会仅依靠这些数字来确定是否使用了数据库(也可能有自动化流程正在使数据库看起来是最新的,即使您不关心删除数据库时这些自动化过程会失败)。
另一个注意事项是在索引使用视图中可能不会跟踪某些索引访问;例如,在添加内存优化表的 SQL Server 2014 中,不会以这种方式捕获针对这些哈希索引的活动(并且您认为会捕获活动的视图,例如sys.dm_db_xtp_hash_index_stats
,不包括任何日期/时间列)。如果您使用 SQL Server 2014 和内存中 OLTP(“Hekaton”),您可能需要添加一些研究来涵盖这些对象(以防它们是数据库中唯一引用的对象)。
还有一点要注意的是,捕获的查询sys.dm_exec_query_stats
可能是误报。例如,如果您的数据库有filestream
/ filetable
,您会看到系统偶尔运行这些查询:
select table_id, item_guid, oplsn_fseqno, oplsn_bOffset, oplsn_slotid
from [database].[sys].[filetable_updates_<some_id>] with (readpast) order by table_id
Run Code Online (Sandbox Code Playgroud)
因此,您可能希望向上述查询添加额外的过滤以过滤掉它们(只要过滤器不会意外过滤掉您关心的查询)。这可能是对该派生表的安全补充:
AND t.[text] NOT LIKE N'%oplsn_fseqno%'
Run Code Online (Sandbox Code Playgroud)
最后,在开发环境中最安全的做法是将您不确定的数据库离线一周。如果没有人抱怨,请支持他们,然后放弃他们。如果某人需要一个多星期的时间才能注意到他们失踪了,您可以随时恢复他们(在那里或其他地方)。
我也在博客上写了一点: