数据库大小-MDF太大?


10

我正在维护一个SQL Server 2005数据库,该数据库承载大约2.9Tb的数据(2 x 1.45Tb-我具有RAW架构和Analysis架构,因此基本上是摄取的数据的两个副本)。恢复模型为SIMPLE,恢复模型为.ldf6Gb。

无论出于什么原因,它.mdf都是7.5Tb。现在,在Analysis表中可能只有2-3个附加列,NVARCHAR(MAX)而从我(可能是误解-如果我错了,请纠正我)可能导致额外的空间分配的列不多。那是在紧缩数据库之后-在此之前大约是9Tb。有什么想法吗?

并且,如果您还有其他问题,请告诉我-我是数据库管理和优化工作的新手(我通常不做这方面的工作:)。

非常感谢!

安德里亚


谢谢Marc-以任何方式可以将这个问题移到那里,还是需要重新发布?

干杯-您可能猜到了,我是新来的:)

Answers:


11

在大小估计中,您是否考虑了索引占用的空间量?另外,如果您将文本字段设置为多字节(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.objectssys.dm_db_partition_stats上述第一个查询中使用,请参阅http://technet.microsoft.com/en-us/library/ms177862.aspx对于更多的细节),以获得更多的细节,如每个索引使用的空间。


数据文件中有三类未使用的空间:

  1. 没有分配给任何sp_spaceused对象的对象(这在第一个结果集中显示,未指定对象)
  2. 分配给对象(保留)但当前未使用的对象(这显示在sp_spaceused的输出中的“未使用”计数中)。
  3. 锁定在部分使用的页面中(这看起来将被使用,因为所有内容都分配在单个页面块中,一个页面长8,192字节)。这很难检测/计算。这是由于两个因素的混合:
    • 分割页面。随着数据的添加,您通常最终会得到部分空白页面(存储引擎可以始终对页面内容进行规范化,但这效率非常低),并且随着行的删除,页面内容不会自动打包(同样可以,但是可能会多余) I / O负载通常从值得的)。
    • 存储引擎不会在多页上拆分行(以及每行8,192字节限制所来自的页大小)。如果您的行是固定大小,每行占用1,100个字节,那么您将“浪费”分配给该表的每个数据块的至少492个字节(7行占用7,700个字节,第8行将不适合,因此剩余字节将被占用)不能使用)。行越宽,情况可能越糟。具有可变长度行(比完全固定长度行更常见)的表/索引通常更好(但不太容易计算问题)。
      这里的另一个警告是大型物体(TEXT列,[N]VARCHAR(MAX) 大于一定大小的值,依此类推),因为它们确实会放在页外,仅在主行数据中占用8个字节来保存指向其他位置的数据的指针),因此可以突破每行限制8,192字节。

tl; dr:估计预期的数据库大小可能比最初设想的要复杂得多。


大卫-非常感谢您的详细回复!我现在正在分析数据库,您和Kenneth的回答都对我了解影响数据库大小的因素有很大帮助。我一直都在关注效率(在数据摄取和数据使用方面),你们提供的信息非常宝贵!
Andrija_Bgd

6

尝试sp_spaceused在数据库上运行。作为示例,它返回:

reserved           data               index_size         unused
------------------ ------------------ ------------------ ------------------
6032 KB            2624 KB            1664 KB            1744 KB

要在数据库上运行它,只需USE运行数据库sp_spaceused

如果仍然显示大量未使用的空间,则可以再次尝试缩小。有时我确实发现它需要多次尝试。同样,有时我发现缩小单个文件而不是缩小整个数据库最有效。但是,您可能会发现,您有2.9Tb的数据和另外4 + Tb的索引,在这种情况下7.5TB是相当合理的。如果您想了解每个表的空间量(数据和索引),那么也可以sp_spaceused在表级别运行。您可以使用以下命令在数据库中的所有表上运行它:

EXEC sp_msforeachtable 'EXEC sp_spaceused [?];'

尽管没有公开警告sp_msforeachtable,但不支持它,并且已知会丢失表。另一方面,我本人也很幸运。

所有这些都说明数据库应该具有一定百分比的可用空间,具体取决于您的预期增长。基本上,您要确保有6个月到数年的增长空间。另外,您将需要检查您的autogrowth设置以确保它们适合您的情况。特别是考虑到数据库的大小,您不想使用%autogrowth


谢谢!我使用了sp_spaceused,看起来实际数据确实占用了指示的空间量,考虑到已加载的平面文件的实际大小,这听起来可能很奇怪……索引很小(我没有t创建了任何其他表,因为在我的情况下,它们将是更多的障碍而不是帮助),所以我想那只是实际的表很大...谢谢您一百万!
Andrija_Bgd 2013年

数据库确实比平面文件占用更多的空间。行和表结构存在一定数量的开销,并且由于页面结构而导致一定数量的浪费。
肯尼斯·费舍尔

-1

使用SQL Management Studio,1.右键单击数据库,然后2.单击任务->收缩->文件

您将看到一个对话框,显示:当前分配的空间b。可用空间+(%free)

如果您的%Free超过50%,则可以考虑缩小文件。我已经看到这种点击率高达90%。如果决定缩小文件,通常将其设置为比当前分配的空间大2或3个演出。我的大多数数据库都小于50gig。因此,如果您的文件更大,则可以将其设置为10 gig。我通常只担心如果要将数据库移动到另一台服务器时会收缩,您可以在任何sql页面上阅读有关收缩问题的全部信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.