长话短说
我正在寻找一种方法来有效地识别最靠近SQL Server数据文件末尾的对象。这种方法需要保持对大型数据文件的性能。
到目前为止我所拥有的
以下查询使用 SQL 2012 附带的未记录的动态管理函数:sys.dm_db_database_page_allocations
; 这个 DMF 提供了一个粗略的DBCC IND
命令等价物。
以下查询标识给定数据文件中的最后一个对象(警告:不要对大于 25 GB 的数据库运行此查询,除非您想在某个时候取消它):
-- Return object with highest Extent Page ID
SELECT files.name as logical_file_name
, files.physical_name as physical_file_name
, OBJECT_SCHEMA_NAME(object_id) + N'.' + OBJECT_NAME(object_id) AS object_name
, alloc.*
FROM sys.dm_db_database_page_allocations(DB_ID(), NULL, NULL, NULL, NULL) alloc
INNER JOIN sys.database_files files
ON alloc.extent_file_id = files.file_id
WHERE is_allocated = 1
AND files.name = 'Logical_FileName'
ORDER BY files.name , files.physical_name, extent_page_id DESC
这种方法有什么问题
正如上面的警告所暗示的那样,随着数据库大小的增加,此查询将运行得更慢,因为该函数实际上是为查看特定对象而不是查看有问题的特定数据文件的有针对性的方法而设计的。当像我一样传递NULL
参数时,此函数可能会在后台遍历数据库中的所有对象并吐出组合输出。这完成了我需要的,但它以一种非常蛮力的方式完成,不适合优化。
我要的是什么
我希望有一种方法可以遍历GAM、SGAM和/或IAM 链,以快速识别给定数据文件末尾的对象。我假设我必须将这种方法从 TSQL 推到 PowerShell 之类的东西,然后返回使用DBCC PAGE调用或类似的东西,遍历页面分配映射以查找给定数据文件的最后一个对象是什么。...我希望有人已经将这些代码放在一起,或者比我更了解这些结构和/或这些未记录程序的输出。
为什么我需要这个?
这是许多人不可避免会问的问题,所以我只是开门见山地回答一下。我一直在做的项目是让遗留系统加快速度,但是在将一堆堆表整合在一起之后(由于其他原因这是一场噩梦),我现在在我的数据中留下了一堆可用空间文件。我想将这个空间释放回操作系统,但是,将对象迁移到不同数据文件的传统方法在这个阶段不可行,因为我没有足够的可用空间在系统上使用(直到我能够从此数据文件中释放更多空间)。
我采取了禁用文件增长并DBCC SHRINKFILE TRUNCATEONLY
每晚运行命令来释放数据文件末尾的所有打开页面的方法,但这是一个缓慢而艰巨的过程,可能会经常发生,也可能不会发生。我希望确定文件末尾的对象是什么,以便我可以手动重建它们并在更快的时间表中释放空间。
总之
有没有办法快速识别位于给定数据文件末尾的对象的名称?我现在使用的方法不能满足我的需求,我愿意使用任何可用的方法。