【问题标题】:Considerations when dropping columns in large tables在大表中删除列时的注意事项
【发布时间】:2011-02-23 00:26:49
【问题描述】:

我有一个呼叫数据表,它已经增长到 13 亿行和 173 GB 的数据。有两列我们不再使用,一列是 char(15),另一列是 varchar(24)。它们都被 NULL 插入了一段时间,我一直在推迟删除列,因为我不确定其中的含义。我们在包含数据库的驱动器和包含事务日志的驱动器上的空间都有限。

此外,我发现this post 说在完成 DBCC REINDEX 之前该空间不可用。我认为这有好有坏。这很好,因为删除列应该非常快并且不涉及大量日志记录,但不好,因为不会回收空间。新插入的记录会占用更少的空间吗?就我而言,这很好,因为我们会在 18 个月后修剪旧数据,因此空间会逐渐减少。

如果我们执行 DBCC REINDEX(或 ALTER INDEX REBUILD),是否真的会有所帮助,因为列不是任何索引的一部分?这会占用日志空间或锁定表使其无法使用吗?

【问题讨论】:

  • 您能否给出确切的表架构,以便我们了解删除这些列可能对每页的行数产生什么影响?

标签: sql-server sql-server-2005


【解决方案1】:

我发现您的问题很有趣,因此决定在开发数据库上对其进行建模。 SQL Server 2008,数据库大小 400 Mb,日志 2.4 Gb。 我假设,从链接提供的你创建了一个带有聚集索引的表:

CREATE TABLE [dbo].[big_table](
    [recordID] [int] IDENTITY(1,1) NOT NULL,
    [col1] [varchar](50) NOT NULL,
    [col2] [char](15) NULL,
    [col3] [varchar](24) NULL,
 CONSTRAINT [PK_big_table] PRIMARY KEY CLUSTERED 
(
    [recordID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] 

此表包含 1200 万条记录。

sp_spaceused big_table, true

name-big_table, rows-12031303, reserved-399240 KB, data-397760 KB, index_size-1336 KB, unused-144 KB. 

删除列

sp_spaceused big_table, true

表格大小保持不变。数据库和日志大小保持不变。

向表的其余部分添加 300 万行

name-big_table, rows-15031303, reserved-511816 KB, data-509904 KB, index_size-1752 KB, unused-160 KB.

数据库大小 500 Mb,日志 3.27 Gb。

之后

DBCC DBREINDEX( big_table )

日志大小相同,但数据库大小增加到 866 Mb

name-big_table, rows-12031303, reserved-338376 KB, data-337704  KB, index_size-568 KB, unused-104 KB. 

再次添加 300 万行以查看它们是否进入数据库中的可用空间。 数据库大小相同,日志 3.96 Gb,这清楚地表明它们是。

希望它有意义。

【讨论】:

  • 添加 300 万行后,您的行数似乎仍为 12031303,这是复制/粘贴错误还是 sp_spaceused 的问题?同样在重新索引之后,它显示了 1200 万行,与最初的 397mb 相比,338mb 的数据大小更小......
  • 哎呀雏菊!复制+粘贴错误。试图制作漂亮的格式。顺便说一句:您需要添加记录的代码吗?如果您愿意,可以在您的开发数据库中检查它。
  • 数据与“sp_spaceused big_table, true”显示的完全一样。请注意,mdf fila 的实际大小有所增加。
【解决方案2】:

不,新插入的记录不会占用更少的空间。我今天早些时候正在研究这个确切的问题,因为它发生了。

测试表

CREATE TABLE T
(
id int identity primary key,
FixedWidthColToBeDropped char(10),
VariableWidthColToBeDropped varchar(10),
FixedWidthColToBeWidened char(7),
FixedWidthColToBeShortened char(20),
VariableWidthColToBeWidened varchar(7),
VariableWidthColToBeShortened varchar(20),
VariableWidthColWontBeAltered varchar(20)
)

偏移量查询

WITH T
     AS (SELECT ISNULL(LEFT(MAX(name), 30), 'Dropped')  AS column_name,
                MAX(column_id)                          AS column_id,
                ISNULL(MAX(case
                             when column_id IS NOT NULL THEN max_inrow_length
                           END), MAX(max_inrow_length)) AS max_inrow_length,
                leaf_offset,
                CASE
                  WHEN leaf_offset < 0 THEN SUM(CASE
                                                  WHEN column_id IS NULL THEN 2 ELSE 0
                                                END)
                  ELSE MAX(max_inrow_length) - MAX(CASE
                       WHEN column_id IS NULL THEN 0
                       ELSE max_inrow_length
                                                   END)
                END                                     AS wasted_space
         FROM   sys.system_internals_partition_columns pc
                JOIN sys.partitions p
                  ON p.partition_id = pc.partition_id
                LEFT JOIN sys.columns c
                  ON column_id = partition_column_id
                     AND c.object_id = p.object_id
         WHERE  p.object_id = object_id('T')
         GROUP  BY leaf_offset)
SELECT CASE
         WHEN GROUPING(column_name) = 0 THEN column_name
         ELSE 'Total'
       END               AS column_name,
       column_id,
       max_inrow_length,
       leaf_offset,
       SUM(wasted_space) AS wasted_space
FROM   T  
GROUP  BY ROLLUP ((column_name,
                   column_id,
                   max_inrow_length,
                   leaf_offset))
ORDER  BY GROUPING(column_name),
          CASE
            WHEN leaf_offset > 0 THEN leaf_offset
            ELSE 10000 - leaf_offset
          END  

表格的初始状态

column_name                    column_id   max_inrow_length leaf_offset wasted_space
------------------------------ ----------- ---------------- ----------- ------------
id                             1           4                4           0
FixedWidthColToBeDropped       2           10               8           0
FixedWidthColToBeWidened       4           7                18          0
FixedWidthColToBeShortened     5           20               25          0
VariableWidthColToBeDropped    3           10               -1          0
VariableWidthColToBeWidened    6           7                -2          0
VariableWidthColToBeShortened  7           20               -3          0
VariableWidthColWontBeAltered  8           20               -4          0
Total                          NULL        NULL             NULL        0

现在进行一些更改

ALTER TABLE T 
ALTER COLUMN FixedWidthColToBeWidened char(12)

ALTER TABLE T 
ALTER COLUMN FixedWidthColToBeShortened char(10)

ALTER TABLE T 
ALTER COLUMN VariableWidthColToBeWidened varchar(12)

ALTER TABLE T 
ALTER COLUMN VariableWidthColToBeShortened varchar(10)

ALTER TABLE T 
DROP COLUMN FixedWidthColToBeDropped, VariableWidthColToBeDropped

再看表

column_name                    column_id   max_inrow_length leaf_offset wasted_space
------------------------------ ----------- ---------------- ----------- ------------
id                             1           4                4           0
Dropped                        NULL        10               8           10
Dropped                        NULL        7                18          7
FixedWidthColToBeShortened     5           10               25          10
FixedWidthColToBeWidened       4           12               45          0
Dropped                        NULL        10               -1          2
VariableWidthColToBeWidened    6           12               -2          0
Dropped                        NULL        20               -3          2
VariableWidthColWontBeAltered  8           20               -4          0
VariableWidthColToBeShortened  7           10               -5          0
Total                          NULL        NULL             NULL        31

插入一行并查看页面

INSERT INTO T
           ([FixedWidthColToBeWidened]
           ,[FixedWidthColToBeShortened]
           ,[VariableWidthColToBeWidened]
           ,[VariableWidthColToBeShortened])
     VALUES
           ('1','2','3','4')

DECLARE @DBCCPAGE nvarchar(100)

SELECT TOP 1  @DBCCPAGE = 'DBCC PAGE(''tempdb'',' + CAST(file_id AS VARCHAR) + ',' + CAST(page_id AS VARCHAR) + ',3)'
FROM T
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%) 

DBCC TRACEON(3604)
EXEC (@DBCCPAGE)    

返回

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 75                     
Memory Dump @0x000000000D5CA060

0000000000000000:   30003900 01000000 26a44500 00000000 †0.9.....&¤E..... 
0000000000000010:   ffffffff ffffff7f 00322020 20202020 †ÿÿÿÿÿÿÿ..2       
0000000000000020:   20202003 00000000 98935c0d 00312020 †   ......\..1   
0000000000000030:   20202020 20202020 200a0080 00050049 †         ......I 
0000000000000040:   004a004a 004a004b 003334†††††††††††††.J.J.J.K.34      

Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4

id = 1                               

Slot 0 Column 67108868 Offset 0x8 Length 0 Length (physical) 10

DROPPED = NULL                       

Slot 0 Column 67108869 Offset 0x0 Length 0 Length (physical) 0

DROPPED = NULL                       

Slot 0 Column 67108865 Offset 0x12 Length 0 Length (physical) 7

DROPPED = NULL                       

Slot 0 Column 67108866 Offset 0x19 Length 0 Length (physical) 20

DROPPED = NULL                       

Slot 0 Column 6 Offset 0x49 Length 1 Length (physical) 1

VariableWidthColToBeWidened = 3      

Slot 0 Column 67108867 Offset 0x0 Length 0 Length (physical) 0

DROPPED = NULL                       

Slot 0 Column 8 Offset 0x0 Length 0 Length (physical) 0

VariableWidthColWontBeAltered = [NULL]                                    

Slot 0 Column 4 Offset 0x2d Length 12 Length (physical) 12

FixedWidthColToBeWidened = 1                                              

Slot 0 Column 5 Offset 0x19 Length 10 Length (physical) 10

FixedWidthColToBeShortened = 2                                            

Slot 0 Column 7 Offset 0x4a Length 1 Length (physical) 1

VariableWidthColToBeShortened = 4    

Slot 0 Offset 0x0 Length 0 Length (physical) 0

KeyHashValue = (010086470766)      

您可以看到删除(和更改)的列仍在消耗空间,即使在更改架构时表实际上是空的。

在您的情况下,删除列的影响将是 15 浪费了 char 一个字节和 varchar 一个 2 个字节除非它是变量中的最后一列不占用空间的部分。

【讨论】:

    猜你喜欢
    • 2017-09-14
    • 2013-02-03
    • 1970-01-01
    • 2015-10-31
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    相关资源
    最近更新 更多