在大小估计中,您是否考虑了索引占用的空间量?另外,如果您将文本字段设置为多字节(N[VAR]CHAR
而不是[VAR]CHAR
),并且输入文件是UTF-8或每个字符一个普通字节,那么这将使您的存储需求最多增加两倍。此外,请记住,如果表上有聚簇键/索引,则其大小会影响表上的所有其他索引,因为它们包括每一行的聚簇键值(因此,如果表具有NCHAR(10 )一个INT会做的键,那就是您的聚集键/索引,您不仅在数据页的每行额外使用16个字节,而且在该表的其他索引中每行浪费16个字节()。
另外,将分配一些空间,但未使用这些空间,这是因为DB引擎在删除后留下了一些分配的空间,以便可以再次将其快速用于该表中的新数据,或者因为插入和删除的模式仅使许多页面保留了一部分充分。
您可以运行:
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
快速查看哪些表占用了空间。
此外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
上面的代码将在一个列表中输出所有表的大小,并在总数中加一行。如果需要,您可以使用各种系统的意见(如sys.objects
与sys.dm_db_partition_stats
上述第一个查询中使用,请参阅http://technet.microsoft.com/en-us/library/ms177862.aspx对于更多的细节),以获得更多的细节,如每个索引使用的空间。
数据文件中有三类未使用的空间:
- 没有分配给任何
sp_spaceused
对象的对象(这在第一个结果集中显示,未指定对象)
- 分配给对象(保留)但当前未使用的对象(这显示在
sp_spaceused
的输出中的“未使用”计数中)。
- 锁定在部分使用的页面中(这看起来将被使用,因为所有内容都分配在单个页面块中,一个页面长8,192字节)。这很难检测/计算。这是由于两个因素的混合:
- 分割页面。随着数据的添加,您通常最终会得到部分空白页面(存储引擎可以始终对页面内容进行规范化,但这效率非常低),并且随着行的删除,页面内容不会自动打包(同样可以,但是可能会多余) I / O负载通常远从值得的)。
- 存储引擎不会在多页上拆分行(以及每行8,192字节限制所来自的页大小)。如果您的行是固定大小,每行占用1,100个字节,那么您将“浪费”分配给该表的每个数据块的至少492个字节(7行占用7,700个字节,第8行将不适合,因此剩余字节将被占用)不能使用)。行越宽,情况可能越糟。具有可变长度行(比完全固定长度行更常见)的表/索引通常更好(但不太容易计算问题)。
这里的另一个警告是大型物体(TEXT
列,[N]VARCHAR(MAX)
大于一定大小的值,依此类推),因为它们确实会放在页外,仅在主行数据中占用8个字节来保存指向其他位置的数据的指针),因此可以突破每行限制8,192字节。
tl; dr:估计预期的数据库大小可能比最初设想的要复杂得多。