AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 169254
Accepted
ajeh
ajeh
Asked: 2017-04-06 13:49:01 +0800 CST2017-04-06 13:49:01 +0800 CST 2017-04-06 13:49:01 +0800 CST

尝试压缩现有表不会改变表大小

  • 772

SQL 2012 Enterprise DB 中有一个现有表,其大小约为 120MB,包含约 2000 条记录。它最大的字段是nvarchar(max)包含海绵状的 XML(范围从 20 到 300 kB),它本身在 7Zip 或 RAR 中压缩了大约 50-75%。

我尝试了以下立即返回的命令,即使只是从表中查询 * 需要几秒钟:

alter table sch.table1 REBUILD PARTITION=ALL WITH (DATA_COMPRESSION=ROW)
alter table sch.table1 REBUILD PARTITION=ALL WITH (DATA_COMPRESSION=PAGE)
alter table sch.table1 REBUILD PARTITION=ALL WITH (DATA_COMPRESSION=NONE)

但是在它们中的任何一个之后大小都没有改变,即使表的属性正确地显示了压缩类型。

服务器实际上是否对行/页面应用和删除压缩?它似乎没有时间在执行每个命令的瞬间完成。

sql-server compression
  • 1 1 个回答
  • 1873 Views

1 个回答

  • Voted
  1. Best Answer
    Joe Obbish
    2017-04-06T17:09:27+08:002017-04-06T17:09:27+08:00

    行压缩和页面压缩有许多限制,并且不会总是减少表使用的空间。让我们来看一个简单的例子。假设我将一堆长度为 4030 的字符串插入到表中。应用页面压缩会导致空间从 4000 KB 减少到 24 KB:

    CREATE TABLE dbo.ZZZZZ_CI (
    ID INT NOT NULL IDENTITY (1, 1),
    FLUFF VARCHAR(4050),
    PRIMARY KEY (ID)
    );
    
    SET NOCOUNT ON;
    
    GO
    -- insert 1000 rows
    INSERT INTO dbo.ZZZZZ_CI VALUES (REPLICATE('Z', 4030));
    GO 1000
    
    EXEC sp_spaceused 'dbo.ZZZZZ_CI'; -- 4000 KB for data
    
    ALTER TABLE dbo.ZZZZZ_CI REBUILD WITH (DATA_COMPRESSION=PAGE);
    
    EXEC sp_spaceused 'dbo.ZZZZZ_CI'; -- now 24 KB for data
    

    但是,如果我插入长度为 4050 的字符串,我不会从页面压缩中节省空间,即使这些字符串都是相同的字符!

    -- remove data and compression
    TRUNCATE TABLE dbo.ZZZZZ_CI;
    ALTER TABLE dbo.ZZZZZ_CI REBUILD WITH (DATA_COMPRESSION=NONE);
    
    GO
    -- insert 1000 rows
    INSERT INTO dbo.ZZZZZ_CI VALUES (REPLICATE('Z', 4050));
    GO 1000
    
    EXEC sp_spaceused 'dbo.ZZZZZ_CI'; -- 8000 KB for data
    
    ALTER TABLE dbo.ZZZZZ_CI REBUILD WITH (DATA_COMPRESSION=PAGE);
    
    EXEC sp_spaceused 'dbo.ZZZZZ_CI'; -- still 8000 KB for data
    

    对于您的表,您可能会遇到不同的限制。SQL Server 中的表每行只能包含8060 个字节。任何不适合的数据都单独存储为ROW_OVERFLOW_DATA. 您的平均行大小约为 64 KB,最小行大小为 20 KB。这意味着您的所有 XML 数据都不能存储在行中。数据压缩不适用于存储在行外的数据:

    SQL Server 会压缩行内 LOB 数据,但如果 LOB 数据存储在行外,则不会。因此,许多 LOB 繁重的应用程序无法充分利用数据压缩。但是,有两种解决方法可用。首先,可以在应用层压缩 LOB 数据,但这意味着 (a) 需要修改应用程序 (b) 应用程序无法利用 SQL 引擎中提供的搜索和部分更新功能。其次,使用文件流功能将 LOB 数据存储在压缩卷上。这是我们推荐的适用解决方案。有关文件流功能的详细信息,请参阅 Books-Online。

    SQL Server 2012 中提供了这两种解决方法。在 SQL Server 2016 中,引入了GZIP有一个附加选项。这可以压缩原本会存储在行外的数据。之前的数据无法进行页面压缩,但 GZIP 将所需空间减少到 64 KB:

    CREATE TABLE dbo.ZZZZZ_CI_2016 (
    ID INT NOT NULL IDENTITY (1, 1),
    FLUFF_COMPRESSED varbinary(max),
    PRIMARY KEY (ID)
    );
    
    GO
    -- insert 1000 compressed rows
    INSERT INTO dbo.ZZZZZ_CI_2016 VALUES (COMPRESS(REPLICATE('Z', 4050)));
    GO 1000
    
    EXEC sp_spaceused 'dbo.ZZZZZ_CI_2016';  -- now 64 KB for data
    
    SELECT COUNT(*) -- 1000 is returned
    FROM ZZZZZ_CI_2016
    WHERE DECOMPRESS(FLUFF_COMPRESSED) = REPLICATE('Z', 4050);
    

    即使很长的字符串也可以很好地压缩:

    TRUNCATE TABLE dbo.ZZZZZ_CI_2016;
    
    GO
    -- insert 1000 compressed rows
    INSERT INTO dbo.ZZZZZ_CI_2016 VALUES (COMPRESS(REPLICATE(CAST('Z' AS VARCHAR(MAX)), 99999)));
    GO 1000
    
    EXEC sp_spaceused 'dbo.ZZZZZ_CI_2016';  -- now 152 KB for for 99999 length strings
    
    • 9

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve