了解两个表使用的存储空间的差异

Gal*_*a88 2 sql-server storage sql-server-2016

我有两个表,其中一个或多或少包含另一个的数据子集。我从第一个表中删除了一些数据,这些数据作为历史数据插入到第二个表中。

这些是定义:

CREATE TABLE [dbo].[CIC_DESLUNGHE](
    [CD_CIC_DESLUNGHE] [bigint] IDENTITY(1,1) NOT NULL,
    [CD_CIC_PRODUZIONE] [bigint] NOT NULL,
    [CD_CIC_OPERAZIONI] [bigint] NOT NULL,
    [AFNMPROG] [int] NOT NULL,
    [AFDSLINE] [nvarchar](max) NULL,
 CONSTRAINT [PK_CIC_DESLUNGHE] PRIMARY KEY CLUSTERED 
(
    [CD_CIC_DESLUNGHE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 99) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO


CREATE TABLE [dbo].[CIC_DESLUNGHE_STORICI](
    [CD_CIC_DESLUNGHE_STORICI] [bigint] IDENTITY(1,1) NOT NULL,
    [CD_CIC_PRODUZIONE_STORICI] [bigint] NOT NULL,
    [CD_CIC_OPERAZIONI_STORICI] [bigint] NOT NULL,
    [AFNMPROG] [int] NOT NULL,
    [AFDSLINE] [nvarchar](max) NOT NULL,
 CONSTRAINT [PK_CIC_DESLUNGHE_STORICI_1] PRIMARY KEY CLUSTERED 
(
    [CD_CIC_DESLUNGHE_STORICI] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

第二个表包含我需要它作为我的数据的历史化的数据子集。

Table                   Rows        TotalSpace MB
---------------------   ----------  -------------
CIC_DESLUNGHE_STORICI   12.709.497  48214,75
CIC_DESLUNGHE           24.827.337  5675,49
Run Code Online (Sandbox Code Playgroud)

让我惊讶的是使用的总存储空间。子集表使用其他表的 10 倍空间。

知道为什么会这样吗?

我尝试重建 的聚集索引CIC_DESLUNGHE_STORICI,但存储仅从 48 GB 下降到 47 GB。

- 编辑 -

这是我通过 Josh Darnell 的查询得到的结果

CIC_DESLUNGHE

CIC_DESLUNGHE_STORICI

Jos*_*ell 6

根据给出的信息,一种解释是存储在nvarchar(max)列中的数据大小曾经比现在大得多。

  • 约 1200 万历史行,平均每行 3.88 KB
  • 约 2400 万行,平均每行 0.23 KB

您可以通过在两个表中的每一个上使用动态管理函数sys.dm_db_index_physical_stats来仔细检查这一点,特别是查看“avg_record_size_in_bytes”列。像这样的东西:

SELECT 
    DB_NAME(ips.database_id),
    OBJECT_NAME(ips.[object_id]),
    ips.index_id,
    ips.index_type_desc,
    ips.index_level,
    ips.alloc_unit_type_desc,
    ips.page_count,
    ips.record_count,
    ips.min_record_size_in_bytes,
    ips.max_record_size_in_bytes,
    ips.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats 
(
    DB_ID(N'YourDatabaseName'), 
    OBJECT_ID(N'CIC_DESLUNGHE'), 
    NULL, 
    NULL , 
    'DETAILED'
) ips;
Run Code Online (Sandbox Code Playgroud)

SELECT 
    DB_NAME(ips.database_id),
    OBJECT_NAME(ips.[object_id]),
    ips.index_id,
    ips.index_type_desc,
    ips.index_level,
    ips.alloc_unit_type_desc,
    ips.page_count,
    ips.record_count,
    ips.min_record_size_in_bytes,
    ips.max_record_size_in_bytes,
    ips.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats 
(
    DB_ID(N'YourDatabaseName'), 
    OBJECT_ID(N'CIC_DESLUNGHE_STORICI'), 
    NULL, 
    NULL , 
    'DETAILED'
) ips;
Run Code Online (Sandbox Code Playgroud)

比较两次查询的结果,看看是否有任何令人惊讶的差异。

我将其他过滤器排除在函数调用之外,因为这也将显示非聚集索引。您没有提到您是如何得出问题中的数字的,但是如果它们在表格中包含 NC 索引,则这些索引可能会导致大小差异。