从TFS迁移到VSTS - 减少TPC数据库大小

时间:2018-03-16 09:58:10

标签: tfs migration azure-devops dacpac

我们计划很快从内部部署TFS实例迁移到VSTS。在迁移之前,我们运行先决条件验证任务并获得有关TPC数据库大小的以下输出报告:

“数据库目前是191GB。这超过了建议的150GB大小,使用DACPAC导入方法。最大的表大小目前是172GB。这超过了建议的20GB大小使用DACPAC导入方法。

验证已完成'验证集合数据库大小',结果警告,消息最大表大小目前为172GB。这超过了使用DACPAC导入方法的建议大小20GB。“

因此,我们热衷于减少TPC数据库的大小,并有两个主要考虑因素:

  1. 缩小数据库并从结果输出中生成DACPAC。

  2. 删除以下任何未使用或冗余的对象:

    a)较旧的工作区
    b)建立结果
    c)冗余团队项目
    d)未使用的文件
    e)测试运行期间创建的测试附件
    f)XAML构建

  3. 因此,对于任何一种方法的利弊得到一些建议或反馈,我们将不胜感激。

1 个答案:

答案 0 :(得分:3)

鉴于您需要将最大的表减少150GB,我想知道DACPAC是否会成为一种选择。也就是说,清理TFS实例总是一个好主意。在您设法剥离足够的数据以实际获得收益之外,您的第一步将无济于事。

您确定的行动确实有帮助,most are already documented here。有助于检测空间分配位置的查询也是found in this recent support ticket

删除旧工作区

删除工作区和搁置集可以大大减少迁移和升级时间。使用tf命令行或利用TFS SideKicks之类的工具来识别和删除这些命令。

构建结果

不仅仅是构建结果,而且经常忽略实际构建记录会占用大量数据。使用tfsbuild destroy(XAML)永久删除构建记录。在过去,我遇到的客户在他们的数据库中有180万个“隐藏”版本,删除它们会削减相当多的数据。这些记录保存在仓库周围。

旧团队项目

当然,销毁旧团队项目可以回馈大量数据。你不需要发送给azure的任何东西都有帮助。你也可以考虑splitting the collection并留下旧项目。如果您再次需要这些数据,那么这将为您提供分离该集合并将其存储在某处的选项。

冗余文件

已删除的分支是一种非常常见的隐藏大小的猪。在TFVC中删除内容时,它们实际上并未删除,只是隐藏了它们。查找已删除的文件,特别是旧的开发或功能分支可以为您提供大量数据。使用tf destroy摆脱它们。

您可能还想查找已检入的nuget包文件夹,这些文件夹也可以快速占用大量空间。

测试附件

哦,是的,尤其是当您使用测试附件时,这些可能会变得疯狂,这取决于您的TFS版本是使用内置的测试附件清理功能还是使用Test Attachment Cleaner from the TFS power tools

XAML Builds

构建定义本身不会占用大量的数据库空间,但构建结果可能会占用。但是这些已在前一节中介绍过。

Git存储库

您的git存储库中可能存在由于强制推送或已删除分支而无法再访问的数据。 Git中的某些数据也可能更有效地打包。要清理存储库,必须在本地克隆它们,清理它们,从TFS中删除远程存储库并将清理后的副本推送到新存储库(您可以使用与旧存储库相同的名称)。这样做会破坏现有构建定义的引用,您必须解决这些问题。在您使用它的同时,您还可以运行BFG repo Cleaner and convert the repositories to enable Git-LFS support来更优雅地处理存储库中的大型二进制文件。

git clone --mirror <<repo>>
# optionally run BFG repo cleaner at thi s point
git reflog expire --expire=now --all 
git gc --prune=now --aggressive
git repack -adf
# Delete and recreate the remote repository with the same name
git push origin --all
git push origin --tags

工作项目(附件)

工作项可以收集大量数据,尤其是当人们开始将大型附件附加到他们身上时。您可以使用witadmin destroywi删除包含不合理大附件的工作项。要保留工作项,但删除其附件,可以从当前工作项中删除附件,然后克隆它。克隆后,销毁旧工作项以允许清理附件。

您不再需要的旧工作项(例如6年前的冲刺)也可以删除。我的同事雷内有nice tool that allows you to bulk-destroy by first creating the appropriate work item query

确保运行清理作业

TFS通常不会直接从数据库中删除数据,在许多情况下,它只会将内容标记为已删除以进行最新处理。要强制立即执行清理,请在Project Collection数据库上运行以下存储过程:

EXEC prc_CleanupDeletedFileContent 1
# You may have to run the following command multiple times, the last
# parameter is the batch size, if there are more items to prune than the 
# passed in number, you will have to run it multiple times
EXEC prc_DeleteUnusedFiles 1, 0, 100000

其他有用的查询

要确定每个部分中存储的数据量,there are a few useful queries you can ru n。实际查询取决于您的TFS版本,但由于您正在准备迁移,我怀疑您目前正在使用TFS 2017或2018。

找到最大的表格:

SELECT TOP 10 o.name, 
SUM(reserved_page_count) * 8.0 / 1024 SizeInMB,
SUM(CASE 
WHEN p.index_id <= 1 THEN p.row_count
ELSE 0
END) Row_Count
FROM sys.dm_db_partition_stats p
JOIN sys.objects o
ON p.object_id = o.object_id
GROUP BY o.name
ORDER BY SUM(reserved_page_count) DESC

找到最大的内容提供者:

SELECT Owner = 
CASE
WHEN OwnerId = 0 THEN 'Generic' 
WHEN OwnerId = 1 THEN 'VersionControl'
WHEN OwnerId = 2 THEN 'WorkItemTracking'
WHEN OwnerId = 3 THEN 'TeamBuild'
WHEN OwnerId = 4 THEN 'TeamTest'
WHEN OwnerId = 5 THEN 'Servicing'
WHEN OwnerId = 6 THEN 'UnitTest'
WHEN OwnerId = 7 THEN 'WebAccess'
WHEN OwnerId = 8 THEN 'ProcessTemplate'
WHEN OwnerId = 9 THEN 'StrongBox'
WHEN OwnerId = 10 THEN 'FileContainer'
WHEN OwnerId = 11 THEN 'CodeSense'
WHEN OwnerId = 12 THEN 'Profile'
WHEN OwnerId = 13 THEN 'Aad'
WHEN OwnerId = 14 THEN 'Gallery'
WHEN OwnerId = 15 THEN 'BlobStore'
WHEN OwnerId = 255 THEN 'PendingDeletion'
END,
SUM(CompressedLength) / 1024.0 / 1024.0 AS BlobSizeInMB
FROM tbl_FileReference AS r
JOIN tbl_FileMetadata AS m
ON r.ResourceId = m.ResourceId
AND r.PartitionId = m.PartitionId
WHERE r.PartitionId = 1
GROUP BY OwnerId
ORDER BY 2 DESC

如果文件容器是问题:

SELECT CASE WHEN Container = 'vstfs:///Buil' THEN 'Build'
WHEN Container = 'vstfs:///Git/' THEN 'Git'
WHEN Container = 'vstfs:///Dist' THEN 'DistributedTask'
ELSE Container 
END AS FileContainerOwner,
SUM(fm.CompressedLength) / 1024.0 / 1024.0 AS TotalSizeInMB
FROM (SELECT DISTINCT LEFT(c.ArtifactUri, 13) AS Container,
fr.ResourceId,
ci.PartitionId
FROM tbl_Container c
INNER JOIN tbl_ContainerItem ci
ON c.ContainerId = ci.ContainerId
AND c.PartitionId = ci.PartitionId
INNER JOIN tbl_FileReference fr
ON ci.fileId = fr.fileId
AND ci.DataspaceId = fr.DataspaceId
AND ci.PartitionId = fr.PartitionId) c
INNER JOIN tbl_FileMetadata fm
ON fm.ResourceId = c.ResourceId
AND fm.PartitionId = c.PartitionId
GROUP BY c.Container
ORDER BY TotalSizeInMB DESC