我可以在具有NVARCHAR(MAX)字段的表上放置Clustered ColumnStore索引吗?

时间:2018-05-10 10:40:49

标签: sql sql-server sql-server-2016

我在SQL Server 2016中有一个200 GB数据的表。所以我打算在该表中应用Clustered ColumnStore来进行磁盘压缩以及更好的性能。

但问题是在该表下有一列数据类型是NVARCHAR(MAX),而列存储索引不支持该数据类型。

所以我想的是将数据类型从NVARCHAR(max)更改为任何其他数据类型,该数据类型至少接受同一列中的81446个字符。

我已尝试过SQL中可用的其他一些数据类型,如VARCHAR(8000),但它的作用是删除8000个字符以后的其他数据。

我也试过文字。但是再次在Text中,由于限制,列存储不适用。

那么请你知道我必须使用哪种数据类型。或者有没有其他方法在同一个表中应用ColumnStore索引?

2 个答案:

答案 0 :(得分:3)

您在这里有几个不同的问题:

问:SQL Server 2016可以在列存储索引中使用(MAX)数据类型吗?

没有。 The documentation states

  

表所需时,请勿使用聚簇列存储索引   varchar(max),nvarchar(max)或varbinary(max)数据类型。

我通常会停在那里 - 如果文档告诉你不要做某事,你可能不应该。

问:我可以在VARCHAR(8000)中存储超过8,000个字符吗?

没有。数字表示它所说的内容 - 它是您可以存储的最大字符数。如果您尝试存储其他数据,则无法存活。

问:我可以在没有这些(MAX)字段的情况下构建群集列存储吗?

是的,通过更改您的数据模型并打破表格。假设所涉及的表名为FactTable:

  1. 使用大文本字段创建一个新表 - 我们将其称为FactTable_Text。
  2. 使用其余字段创建一个新表 - 我们将其称为FactTable_Data。将聚集的列存储索引放在此上,您将获得压缩。
  3. 将旧FactTable中的数据迁移到这些新表中
  4. 放下旧桌子
  5. 创建一个名为FactTable的视图,它将FactTable_Data和FactTable_Text连接在一起
  6. 用户继续查询FactTable,而不知道有什么变化
  7. 不幸的是,您可能不得不更改ETL过程,并且根据表中涉及的文本数量,您可能无法获得任何压缩。例如,假设表格大小的90%全部来自文本 - 那么你还没有在这里保存任何东西。

    现在你开始明白为什么文档会告诉你这不是一个好主意。

答案 1 :(得分:0)

使用 LOB 列减小表大小的另一种解决方案是在存储和读取 LOB 内容时使用 SQL Server 的本机 COMPRESS() 和 DECOMPRESS() 函数。 这是 Microsoft docs 的链接。

当我发现存储在 varchar(max) 列中的 30MB json 文件根本没有被任何表压缩方法压缩时,我开始使用 COMPRESS() 和 DECOMPRESS()。 COMPRESS() 使它们缩小到原始尺寸的 5% 以下。 压缩 varchar(max)、nvarchar(max) 和 varbinary(max) 格式工作正常。

DECOMPRESS() 将返回一个二进制文件,因此请确保在需要时将其转换或转换为原始格式(varchar 或 nvarchar)。

关于性能损失,我不能说太多。有一些,但性能仍然非常适合我需要做的事情。

COMPRESS() 使用 Gzip 压缩标准。支持 Gzip 的 ETL 工具可以将已经压缩的内容写入 SQL Server,以便稍后使用 DECOMPRESS() 读取。至少 C#/.NET/SSIS 可以。我在 stackoverflow 上发现了一个 very usable C# code example