使用聚集列存储索引向表添加新列

Ket*_*tan 1 sql-server columnstore sql-server-2016

我有一个FactsTable1包含 240 列的每日事实表 ' ',我正在其中探索 ' Clustured Columnstore Index'(CCI)。

我想知道,

  • 当我向表中再添加约 50 列时会发生什么?
  • 他们会自动添加到 CCI 吗?或者我必须再次重建CCI?
  • 处理这种情况的最佳方法应该是什么?
  • 如果我必须重建索引以使新列成为 CCI 的一部分,那么如果我不重建会发生什么?它将如何影响我的查询性能?

附加信息 :

  • FactsTable1 包含 400000+ 行和 240 列
  • 它在日期列上分区
  • 它对分析数据的查询量很大。
  • @@版本:Microsoft SQL Server 2016 (RTM) - 13.0.1601.5 (X64)

Sti*_*nts 6

当我向表中添加另外 50 列时会发生什么?

如果您没有指定默认值,这些列将被添加到带有 NULL 值的表中。如果您添加了默认值,则压缩的行组将保持原样,不会进行任何更新。

它们会自动添加到 CCI 中吗?

是的

处理这种情况的最佳方法应该是什么?

如果您要更新新列的所有值,您将获得大量压缩行组,其中包含更多删除的行并打开增量存储(堆),当进行大规模更新时,元组移动器将启动并转动这些增量如果它们被标记为关闭(大小为 1 000 000 行),则存储到压缩段中。要摆脱只剩下几行的压缩段,您必须做一个REORGANIZE声明

附加信息

--> 您至少需要 1 000 000 行才能使 CCI 正常工作,否则您将被困在堆增量存储中。(你只有 400 000)

这将需要您重建或重新组织索引以将所有行放入压缩段

ALTER INDEX idx_cci_target ON cci_target REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON);

您还应该将 SQL Server 2016 升级到 SP1

尝试这个

因为您的事实表中没有这么多行,所以最好使用 NCCI 技巧。您可以在您的表上创建一个空的过滤非聚集列存储索引。这将对您的表产生零成本,但会触发批处理模式执行计划,这将为分析查询带来很多收益。

CREATE NCCI_TEST on TESTABLE (ALL COLUMNS)
WHERE ID = -1 and ID = -2
Run Code Online (Sandbox Code Playgroud)

例子

CREATE TABLE dbo.test
(
Bla datetime,
blabla varchar(200)
)
GO
CREATE CLUSTERED COLUMNSTORE INDEX CCI_TEST on DBO.TEST
GO
Run Code Online (Sandbox Code Playgroud)

然后插入一些行

INSERT INTO dbo.test
select DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0),cast(ABS(CHECKSUM(NEWID())) as varchar)
GO 10000

insert into dbo.test
select * from dbo.test
GO 5
Run Code Online (Sandbox Code Playgroud)

如果你然后去检查你的列存储元素

select * from sys.column_store_row_groups
Run Code Online (Sandbox Code Playgroud)

行存储元素

您会看到您现在拥有一个增量存储,这意味着这是一个没有索引的堆表。

如果然后使用压缩所有行组重建索引

ALTER INDEX CCI_TEST on DBO.TEST REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON)
Run Code Online (Sandbox Code Playgroud)

压缩的

墓碑元素是之前的增量存储/压缩段,它们仍然存在,大约 5 分钟后将被删除

您现在拥有列存储压缩(这将避免锁定问题)

如果我们现在添加一个新列

alter table dbo.test add nondefaultvalue varchar(20)
Run Code Online (Sandbox Code Playgroud)

我们再次检查行组

静止压缩

您仍然拥有行组的良好布局。

如果我们添加具有默认值的另一列并检查行组

alter table dbo.test add defaultvalue varchar(20) not null default('DEFAULT')
Run Code Online (Sandbox Code Playgroud)

行组仍然

但是,如果您决定更新这些值。

UPDATE dbo.test 
set nondefaultvalue = 'DEFAULT'
Run Code Online (Sandbox Code Playgroud)

事情会改变的

OpenDeltastore

我们不再有可以使用的压缩段。如果我们然后尝试重新组织这个索引

ALTER INDEX CCI_TEST on DBO.TEST REORGANIZE
Run Code Online (Sandbox Code Playgroud)

更新后重组

我们再次获得我们的开放增量存储,这将导致锁定。但是,我们可以通过发出我们之前看到的以下命令将其恢复为压缩段

ALTER INDEX CCI_TEST on DBO.TEST REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON)
Run Code Online (Sandbox Code Playgroud)

重新压缩

现在我们必须再次做好列存储段。

因此,在您的情况下,您必须通过压缩所有行组进行重组,以使其正常工作。对于只有 400 000 行的表,这应该不会花费很长时间,但有必要避免锁定。

如果您进行批量插入,故事会再次更改,但您必须一次执行 100 000 行才能将所有内容直接放入压缩段中。

字典

添加另一列时,将为您的列存储索引创建一个新字典(某种映射到列存储段内的列元素)。

select * from sys.column_store_dictionaries

alter table dbo.test add defaultvalue2 varchar(20) not null default('DEFAULT')

select * from sys.column_store_dictionaries
Run Code Online (Sandbox Code Playgroud)

字典

有关更多信息,我建议您访问http://www.nikoport.com/他的博客上提供了您需要的有关 columnstore 的所有额外信息。