曲演杂坛--收缩数据库数据文件
--=====================================================================
部分朋友在遇到收缩数据库文件的时候遇到一些困难,发现明明有大量剩余空间或删除了大量数据,还是无法收缩数据库,这是为啥子呢?
--====================================================================
要收缩数据库文件,首先我们需要确定有多少空间可以收缩,由于收缩文件是按照Extent来收缩,因此我们需要查找有多少未分配的分区。
--======================================================== --查看当前数据库下各文件的占用空间和可收缩空间 --FileSize_MB:当前文件的占用空间 --shrink_space_MB:可以收缩的最大空间(未使用的区所占空间) SELECT DB_NAME() AS DatabaseName ,F.name ,F.physical_name ,F.size*8.0/1024 AS FileSize_MB ,U.total_page_count ,U.allocated_extent_page_count ,U.allocated_extent_page_count/8 AS allocated_extent_count ,U.unallocated_extent_page_count ,U.unallocated_extent_page_count/8 AS unallocated_extent_count ,U.unallocated_extent_page_count*8/1024 AS shrink_space_MB FROM sys.database_files F INNER JOIN sys.dm_db_file_space_usage U ON F.file_id=U.file_id
或者使用
--========================================== ---显示指定的表或视图的数据和索引的碎片信息。 --使用(TotalExtents-UsedExtents)*8*8/1024 得到可以收缩的空间(单位MB)
DBCC SHOWFILESTATS
--===========================================================
在一些情况下,删除了大量数据,但是可以收缩的空间还是很小,这是为什么呢?让我们一步步来分析查找。
首先我们查看数据库上Extent的使用情况
--=========================================== --查看数据库TetDB1的各分区使用情况 CREATE TABLE #TmpExtentInfo ( [file_id] INT, [page_id] BIGINT, [pg_alloc] INT, [ext_size] INT, [object_id] BIGINT, [index_id] INT, [partition_number] INT, [partition_id] BIGINT, [iam_chain_type] VARCHAR(200), [pfs_bytes] VARCHAR(200) ) GO INSERT INTO #TmpExtentInfo EXEC('DBCC EXTENTINFO(''TestDB1'')')
有了所有Extent的使用情况,我们便可以查找在已分配的数据区上未使用的空间情况
--========================================================== --查找在已分配的Extent上未使用的数据页 SELECT OBJECT_NAME(object_id) AS TableName ,index_id ,SUM(ext_size- pg_alloc)*8.0/1024 AS UnusedSpaceInAllocatedExtent_MB FROM #TmpExtentInfo GROUP BY object_id,index_id ORDER BY UnusedSpaceInAllocatedExtent_MB DESC
对于上面有大量未使用空间的用户对象,可以重建索引来释放分区。
--============================================================================================
如果未找到,我们就需要更深一步来数据页的使用情况
--=================================== --创建临时表来存放索引碎片信息 CREATE TABLE #TmpPageFrag ( ObjectName char(255), ObjectId int, IndexName char(255), IndexId int, Lvl int, CountPages int, CountRows int, MinRecSize int, MaxRecSize int, AvgRecSize int, ForRecCount int, Extents int, ExtentSwitches int, AvgFreeBytes int, AvgPageDensity int, ScanDensity decimal, BestCount int, ActualCount int, LogicalFrag decimal, ExtentFrag decimal); --=================================== --使用DBCC SHOWCONTIG来获取索引碎片信息 INSERT INTO #TmpPageFrag EXEC('DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES;') --================================== --查找碎片较大的索引 SELECT * FROM #TmpPageFrag ORDER BY CountPages*(100-AvgPageDensity)/100 DESC
当然我们也可以使用以下脚本来查找
SELECT OBJECT_NAME(object_id) AS TableName,* FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'SAMPLED') ORDER BY page_count*(100-avg_fragmentation_in_percent) DESC
找到碎片较多的索引,可以通过索引维护来释放更多数据页
--===========================================================================================
因为收缩数据库文件是将已分配的页从数据文件的末尾移动到该文件前面的未分配页,因此我们需要先定位哪些“已分配的页”处于数据文件的末尾,由于数据页在文件中的偏移量=页ID*8192,因此页ID越大的数据页,处于文件的越尾端,因此我们需要查找页ID最大的对象
--=========================================== --查看数据库TetDB1的各分区使用情况 CREATE TABLE #TmpExtentInfo ( [file_id] INT, [page_id] BIGINT, [pg_alloc] INT, [ext_size] INT, [object_id] BIGINT, [index_id] INT, [partition_number] INT, [partition_id] BIGINT, [iam_chain_type] VARCHAR(200), [pfs_bytes] VARCHAR(200) ) GO INSERT INTO #TmpExtentInfo EXEC('DBCC EXTENTINFO(''TestDB1'')') --========================================================== --查找在数据文件尾端的对象 SELECT OBJECT_NAME(object_id) AS TableName ,* FROM #TmpExtentInfo ORDER BY page_id DESC
然后对这些索引进行重建,这样便可以将数据页移动到文件前段,从而避免收缩文件时过多的数据页移动。
--=============================================================================
接下来就是收缩啦,这没什么好说的,如果要收缩的空间比较大,可以分多次小空间低收缩。
--============================================================================
在收缩数据库过程中,我们要时刻关注阻塞情况哦,遇到个长期运行的事务,亲,不要不淡定哦!
--===========================================================================
打完收工,依旧是妹子镇贴。
PS: 我会尽量放点小清新的图片,以防止有些兄弟上班时间看妹子被抓到,影响不好!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现