在具有 350 亿行的列存储索引表上重新创建索引
Posted
技术标签:
【中文标题】在具有 350 亿行的列存储索引表上重新创建索引【英文标题】:Recreate index on column store indexed table with 35 billion rows 【发布时间】:2016-11-02 03:09:27 【问题描述】:我有一张大表需要重建索引。该表配置了聚集列存储索引 (CCI),我们意识到我们需要根据特定用例对数据进行排序。
用户执行日期范围和相等查询,但由于数据未按照他们想要的方式排序,因此查询不是最佳的。 SQL 咨询团队建议将数据组织在正确的行组中,以便查询可以从行组消除中受益。
表格说明:
按时间戳 1 分区,每月 PF 总行数:310 亿 预计行大小:60 字节 估计表大小:600 GB表定义:
CREATE TABLE [dbo].[Table1](
[PkId] [int] NOT NULL,
[FKId1] [smallint] NOT NULL,
[FKId2] [int] NOT NULL,
[FKId3] [int] NOT NULL,
[FKId4] [int] NOT NULL,
[Timestamp1] [datetime2](0) NOT NULL,
[Measurement1] [real] NULL,
[Measurement2] [real] NULL,
[Measurement3] [real] NULL,
[Measurement4] [real] NULL,
[Measurement5] [real] NULL,
[Timestamp2] [datetime2](3) NULL,
[TimeZoneOffset] [tinyint] NULL
)
CREATE CLUSTERED COLUMNSTORE INDEX [Table1_ColumnStoreIndex] ON [dbo].[Table1] WITH (DROP_EXISTING = OFF)
GO
环境:
SQL Server 2014 企业版。 8 核,32 GB RAM VMWare 高 性能平台我的策略是:
-
删除现有的 CCI
使用右列创建普通聚集行索引,这将对数据进行排序
使用 DROP EXISTING = OFF 重新创建 CCI。这会将现有的 CRI 转换为 CCI。
我的问题是:
-
重建索引或仅重新加载数据有意义吗?重新加载可能需要一个月才能完成,而重建索引也可能需要很长时间,也许......
如果我删除现有的 CCI,表会扩展,因为它可能不再被压缩?
【问题讨论】:
【参考方案1】:310 亿行是 31,000 个完美的行组,行组只是另一种水平分区,因此加载数据的时间和方式非常重要。 SQL 2014 仅支持离线索引构建。
在考虑创建索引与重新加载时,有一些优缺点:
创建索引是一个单一的操作,所以如果它在任何时候失败,您就会失去进度。对于您的数据量,我不推荐它。 索引构建将创建主字典,因此对于低基数字典编码的列是有益的。 批量加载不会创建主字典,但如果由于某种原因批处理失败,您可以重新加载数据。如果您提供足够的资源,索引构建和批量加载都将是并行的,这意味着您从基本聚集索引中的排序将不会被完美地保留,这只是需要注意的一点;在您的数据规模下,是否有几个重叠的行组无关紧要。
如果您的数据将进行更新/删除并且您重新组织(从 SQL19 也将这样做 Tuple Mover)您的排序可能会随着时间的推移而降级。
我会在date_range
列上创建一个有序的聚集索引并分区,这样每个分区就有50-200 个行组(做一些实验)。然后您可以创建一个分区对齐的聚集列存储索引并一次切换到一个分区,分区切换将触发索引构建,因此您将从主字典中受益,如果您最终在分区上进行更新/删除,您可以通过重建分区而不是整个表来修复索引质量。如果您决定使用 reorganize,您仍会保持某种程度的排序,因为行组只会在同一分区内合并。
【讨论】:
以上是关于在具有 350 亿行的列存储索引表上重新创建索引的主要内容,如果未能解决你的问题,请参考以下文章
在 SQL Server 2017 上创建具有 800+ 百万行的现有分区表的列存储索引
列存储索引中列的顺序在 SQL Server 2012 中是不是重要