And*_*Bgd 10 sql-server-2005 sql-server shrink
我正在维护一个 SQL Server 2005 数据库,该数据库承载大约 2.9Tb 的数据(2 x 1.45Tb - 我有一个 RAW 架构和一个 ANALYSIS 架构,因此基本上是摄取的数据的两个副本)。恢复模型很简单,.ldf
大小为 6Gb。
无论出于何种原因,.mdf
都是 7.5Tb。现在,分析表中可能只有 2-3 个额外的列,并且没有多少NVARCHAR(MAX)
列,根据我的理解(可能有错误理解 - 如果我错了,请纠正我)可能会导致额外的空间分配。那是在刚刚缩小数据库之后 - 在此之前它约为 9Tb。有什么想法吗?
并且,如果您有其他问题,请告诉我 - 我对数据库管理和优化工作非常陌生(我通常不做这方面的工作:))。
非常感谢!
安德里亚
Dav*_*ett 11
在您的大小估计中,您是否考虑了索引占用的空间量?此外,如果您将文本字段设置为多字节(N[VAR]CHAR
而不是[VAR]CHAR
),并且输入文件是 UTF-8 或普通的每字符一个字节,那么这会将您的存储要求提高两倍。此外请记住,如果表上有聚集键/索引,则其大小会影响表上的所有其他索引,因为它们包括每一行的聚集键值(因此如果表具有 NCHAR(10 ) INT 将执行的键,即您的聚集键/索引,您不仅在数据页中每行使用了额外的 16 个字节,而且在该表的每个其他索引中每行浪费了 16 个字节)。
此外,一些空间将被分配但未使用,要么是因为数据库引擎在删除后留下了一些空间,以便它可以快速再次用于该表中的新数据,要么是因为插入和删除的模式只留下了许多页面的一部分满的。
你可以运行:
SELECT o.name
, SUM(ps.reserved_page_count)/128.0 AS ReservedMB
, SUM(ps.used_page_count)/128.0 AS UsedMB
, SUM(ps.reserved_page_count-ps.used_page_count)/128.0 AS DiffMB
FROM sys.objects o
JOIN sys.dm_db_partition_stats ps ON o.object_id = ps.object_id
WHERE OBJECTPROPERTYEX(o.object_id, 'IsMSShipped') = 0
GROUP BY o.name
ORDER BY SUM(ps.reserved_page_count) DESC
Run Code Online (Sandbox Code Playgroud)
快速查看哪些表占用了空间。
同样EXEC sp_spaceused
在该数据库中运行将返回两个结果集。第一个列出在文件系统中为数据文件分配的总空间以及其中有多少未分配,第二个列出了有多少分配的空间用于数据页、索引页或当前未使用。
sp_spaceused
也将返回给定对象使用的空间,因此您可以循环它以构建一个表进行分析:
-- TEMP TABLES FOR ANALYSIS
CREATE TABLE #tTables (sName NVARCHAR(MAX), iRows BIGINT, iReservedKB BIGINT, iDataKB BIGINT, iIndexKB BIGINT, iUnusedKB BIGINT)
CREATE TABLE #tTmp (sName NVARCHAR(MAX), iRows BIGINT, sReservedKB NVARCHAR(MAX), sDataKB NVARCHAR(MAX), sIndexKB NVARCHAR(MAX), sUnusedKB NVARCHAR(MAX))
-- COLLECT SPACE USE PER TABLE
EXEC sp_msforeachtable 'INSERT #tTmp EXEC sp_spaceused [?];'
-- CONVERT NUMBER-AS-TEXT COLUMNS TO NUMBER TYPES FOR EASIER ANALYSIS
INSERT #tTables SELECT sName, iRows
, CAST(REPLACE(sReservedKB, ' KB', '') AS BIGINT)
, CAST(REPLACE(sDataKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sIndexKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sUnusedKB , ' KB', '') AS BIGINT)
FROM #tTmp
DROP TABLE #tTmp
-- DO SOME ANALYSIS
SELECT sName='TOTALS', iRows=SUM(iRows), iReservedKB=SUM(iReservedKB), iDataKB=SUM(iDataKB), iIndexKB=SUM(iIndexKB), iUnusedKB=SUM(iUnusedKB) FROM #tTables ORDER BY sName
SELECT * FROM #tTables ORDER BY iReservedKB DESC
-- CLEAN UP
DROP TABLE #tTables
Run Code Online (Sandbox Code Playgroud)
上面的代码将输出一个列表中的所有表格大小,以及总计的一行。如果需要,您可以使用各种系统视图(如上面第一个查询中使用的sys.objects
和sys.dm_db_partition_stats
使用的,有关更多详细信息,请参见http://technet.microsoft.com/en-us/library/ms177862.aspx)以获取更多详细信息,例如每个索引使用的空间。
数据文件中有三类未使用的空间:
sp_spaceused
没有指定对象的第一个结果集中)sp_spaceused
的输出中的“未使用”计数中。TEXT
列、[N]VARCHAR(MAX)
值超过特定大小等),因为它们确实被放置在页外,只需在主行数据中占用 8 个字节来保存指向其他地方数据的指针),因此可以打破每行 8,192 字节的限制。tl;dr:估计预期的数据库大小可能比最初假设的要复杂得多。
尝试sp_spaceused
在您的数据库上运行。例如,它返回:
reserved data index_size unused
------------------ ------------------ ------------------ ------------------
6032 KB 2624 KB 1664 KB 1744 KB
Run Code Online (Sandbox Code Playgroud)
要在数据库上运行它,只需USE
在数据库上运行sp_spaceused
.
如果它仍然显示大量未使用的空间,您可以再次尝试缩小。有时我确实发现它需要多次尝试。此外,有时我发现缩小单个文件而不是整个数据库效果最好。但是,您可能会发现您有 2.9Tb 的数据和另外 4+Tb 的索引,在这种情况下,7.5TB 是非常合理的。如果您想了解每个表的空间量(数据和索引),那么您也可以sp_spaceused
在表级别运行。您可以使用以下命令在数据库中的所有表中运行它:
EXEC sp_msforeachtable 'EXEC sp_spaceused [?];'
Run Code Online (Sandbox Code Playgroud)
尽管公平警告 sp_msforeachtable 没有记录、不受支持并且已知会丢失表。另一方面,我自己也有相当多的运气。
所有这一切都说你的数据库应该有一定比例的可用空间,这取决于你的预期增长。基本上,您要确保您有 6 个月到几年的增长空间。您还需要检查您的autogrowth
设置以确保它们适合您的情况。特别是考虑到数据库的大小,您不想使用 % autogrowth
。