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

hit*_*126 3 migration tfs dacpac azure-devops

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

“数据库当前为 191GB。这高于使用 DACPAC 导入方法的 150GB 的推荐大小。目前最大的表大小为 172GB。这高于使用 DACPAC 导入方法的 20GB 的推荐大小。

验证完成“验证集合数据库大小”,结果为警告,消息最大表大小当前为 172GB。这超出了使用 DACPAC 导入方法的 20GB 的推荐大小。”

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

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

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

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

因此,希望能就这两种方法的优缺点提供一些建议或反馈,并建议采用哪种方法。

jes*_*ing 8

鉴于您需要将最大的表减少 150GB,我想知道 DACPAC 是否会成为一种选择。也就是说,清理 TFS 实例总是一个好主意。在您设法剥离足够的数据以实际从收缩中获得任何好处之前,您的第一步不会有太大帮助。

您确定的操作确实会有所帮助,大多数已在此处记录在最近的支持服务单中还可以找到有助于检测您的空间分配位置的查询。

删除旧工作区

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

构建结果

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

老团队项目

当然,销毁旧的团队项目可以返还大量数据。您不需要发送到 azure 的任何内容都会有所帮助。您还可以考虑拆分集合并留下旧项目。如果您再次需要该数据,这将使您可以选择分离该集合并将其存储在某处。

冗余文件

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

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

测试附件

哦,是的,尤其是当您使用测试附件时,这些附件可能会变得疯狂,这取决于您的 TFS 版本,要么使用内置的测试附件清理功能,要么使用TFS 强力工具中测试附件清理器

XAML 构建

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

Git 存储库

由于强制推送或删除的分支,您的 git 存储库中的数据可能不再可访问。Git 中的某些数据也有可能更有效地打包。要清理存储库,您必须在本地克隆它们,清理它们,从 TFS 中删除远程存储库并将清理后的副本推送到新存储库(您可以使用与旧存储库相同的名称)。这样做会破坏对现有构建定义的引用,您必须修复它们。在此期间,您还可以运行BFG repo Cleaner 并转换存储库以启用 Git-LFS 支持,从而更优雅地处理存储库中的大型二进制文件。

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
Run Code Online (Sandbox Code Playgroud)

工作项目(附件)

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

您不再需要的旧工作项(例如 6 年前的冲刺项目)也可以删除。我的同事 Rene 有一个很好的工具,它允许您通过首先创建适当的工作项查询来批量销毁

确保运行清理作业

TFS 通常不直接从数据库中修剪数据,在许多情况下它只是将内容标记为已删除以进行最新处理。要强制立即进行清理,请在您的项目集合数据库上运行以下存储过程:

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
Run Code Online (Sandbox Code Playgroud)

其他有用的查询

要确定每个部分中存储了多少数据,您可以运行一些有用的查询。实际查询取决于您的 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
Run Code Online (Sandbox Code Playgroud)

查找最大的内容贡献者:

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
Run Code Online (Sandbox Code Playgroud)

如果文件容器是问题:

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
Run Code Online (Sandbox Code Playgroud)