compress函数不能优化大文本存储,它仅是纯计算函数,返回varbinary(max)且需配对uncompress使用;不支持索引、查询谓词或直接比较;页压缩才是sql server原生存储级压缩方案。

COMPRESS 函数在 SQL Server 2016 中并不能用于优化大文本存储——这是个常见误解。它根本不能用在常规表字段上做存储压缩,也不支持索引、查询谓词或统计信息。
COMPRESS 是纯计算函数,不是存储机制
- 它只接受
VARBINARY或字符串输入,返回VARBINARY(MAX)类型的压缩结果; - 返回值不能直接存入
NVARCHAR、TEXT或XML字段,必须配对使用UNCOMPRESS才能还原; - 压缩后的二进制数据无法被
WHERE、LIKE、JOIN等操作直接使用,因为数据库引擎不理解其内部结构; - 最关键的一点:无法为含
COMPRESS表达式的列创建索引(Microsoft Learn 明确标注:“无法为使用 COMPRESS 函数压缩的数据创建索引”)。
真正可用的大文本压缩方案是页压缩(Page Compression)
SQL Server 的原生数据压缩(行/页压缩)作用于整个表或索引的物理存储层:
- 启用方式是
ALTER TABLE ... REBUILD WITH (DATA_COMPRESSION = PAGE); - 对
VARCHAR(MAX)、XML、TEXT等大对象(LOB)类型仅压缩其内联部分(≤8000 字节),超出部分(即 LOB 数据页本身)不压缩; - 所以:如果你的字段平均长度远超 8KB(比如存日志、HTML、JSON),页压缩对这部分实际效果很弱;
- 压缩率高度依赖数据重复度——比如大量相同前缀的 JSON 字段,页压缩可能有 30%~50% 节省;纯随机文本几乎无收益。
为什么有人误以为 COMPRESS 能优化存储?
- 看到 MySQL 有
COMPRESS()+LONGBLOB组合,就类推 SQL Server; - 实际上 SQL Server 的
COMPRESS设计初衷是为应用层提供一次性的加解密/压缩管道,例如:- 在 ETL 过程中临时压缩中间结果;
- 配合
FILETABLE或VARBINARY列存二进制附件(但需自行管理解压逻辑);
- 它不参与存储引擎的页面组织,也不触发自动解压读取——每次读都要显式调用
UNCOMPRESS,性能开销明显。
容易被忽略的硬限制
-
COMPRESS输入超过 8000 字节时,SQL Server 会静默截断(不报错,但结果不完整); - 返回的
VARBINARY值无法用LEN()准确判断原始长度,得靠DATAlength(); - 如果原始字符串本身就很短(如小于 100 字节),压缩后反而可能更长(zlib 头部开销),此时函数直接返回
NULL; - 在视图、计算列、索引视图中使用
COMPRESS会导致定义失效或报错。
真正要压大文本,优先考虑:归档冷数据、拆分 LOB 到单独表、用 FILESTREAM / FileTable、或迁移到支持透明 LOB 压缩的平台(如 MySQL 8.0 的 ROW_FORMAT=COMPRESSED)。










