Соображения при отбрасывании столбцов в больших таблицах - PullRequest
9 голосов
/ 23 февраля 2011

У меня есть таблица данных вызовов, которая выросла до 1,3 миллиарда строк и 173 гигабайта данных. Есть два столбца, которые мы больше не используем, один - char (15), а другой - varchar (24). Они оба были вставлены с NULL в течение некоторого времени, я откладывал удаление столбцов, потому что я не уверен в последствиях. У нас ограничено пространство как на диске с базой данных, так и на диске с журналом транзакций.

Кроме того, я обнаружил в этом посте о том, что пространство не будет доступно, пока не будет выполнено DBCC REINDEX. Я вижу это как хорошо, так и плохо. Это хорошо, потому что удаление столбцов должно быть очень быстрым и не включать много журналирования, но плохо, потому что пространство не будет освобождено. Будут ли новые вставленные записи занимать меньше места? В моем случае это было бы хорошо, так как мы удаляем старые данные через 18 месяцев, чтобы пространство постепенно уменьшалось.

Если бы мы сделали DBCC REINDEX (или ALTER INDEX REBUILD), это действительно помогло бы, так как столбцы не являются частью какого-либо индекса? Будет ли это занимать место в журнале или блокировать таблицу, чтобы ее нельзя было использовать?

Ответы [ 2 ]

3 голосов
/ 23 февраля 2011

Я нашел ваш вопрос интересным, поэтому решил смоделировать его в базе данных разработки.SQL Server 2008, размер базы данных 400 Мб, журнал 2,4 Гб.Я предполагаю, что по ссылке при условии, что вы создали таблицу с кластерным индексом:

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] 

Эта таблица состоит из 12 миллионов записей.

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

Размер таблицы остается прежним.Размер базы данных и журнала остался прежним.

добавить 3 миллиона строк к остальной таблице

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

размер базы данных 500 МБ, журнал 3,27 ГБ.

После

DBCC DBREINDEX( big_table )

Журнал имеет тот же размер, но размер базы данных увеличился до 866 МБ

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

Снова добавьте 3 миллиона строк, чтобы увидеть, попадут ли они в доступное пространство в базе данных.Размер базы данных тот же, журнал 3,96 Гб, который ясно показывает, что они есть.

Надеюсь, это имеет смысл.

0 голосов
/ 01 марта 2011

Нет, новые записи не будут занимать меньше места. Я смотрел на этот точный вопрос ранее сегодня, как это происходит.

Тестовый стол

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 один и 2 байта для varchar один , если это последний столбец в разделе переменных когда это не займет места.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...