zoukankan      html  css  js  c++  java
  • SQL SERVER 数据压缩

    从SQL SERVER 2008开始,SQL SERVER 提供了对数据进行压缩的功能,启用数据压缩无须修改应用程序。

    数据压缩可有效减少数据的占用空间,读取和写入相同数据花费的IO也响应减少,从而可以有效缓解IO压力,但由于数据在读取和写入时需要压缩和解压缩,因此会消耗CPU资源,但不代表在相同负载下,启用数据压缩会导致CPU的使用率变高,某些操作会因为数据页数量的减少而降低CPU资源的消耗。

    可以配置数据压缩的对象有:
    1>存储为堆的整个表。
    2>存储为聚集索引的整个表。
    3>整个非聚集索引。
    4>整个索引视图。
    5>对于已分区表和已分区索引,可为每个分区配置压缩选项,且对象的各个分区的压缩设置不必相同。
    (个人理解:数据压缩是在parition级别上使用,未分区表和未分区索引同样可以找到一个对应的partitionID)


    数据压缩方式有两种
    1:行压缩
    2:页压缩


    行压缩实现:
    行压缩更改与数据类型相关联的数据的物理存储格式来实现压缩:
    1>减少了与记录相关联的元数据开销。 此元数据为有关列、列长度和偏移量的信息。 在某些情况下,元数据开销可能大于旧的存储格式。
    2>它对于数值类型(例如,integer、decimal 和 float)和基于数值的类型(例如,datetime 和 money)使用可变长度存储格式。
    3>它通过使用不存储空字符的可变长度格式来存储定长字符串。

    快速理解:
    对应数值类型和基于数值的类型来说,由于需要类型定义范围内的数据,因此需要相对较大的定长空间,如BIGINT占用8个字节,但对于值1来说,只需要一个字节便可以存放,启用行压缩便可以节省7个字节的空间;对于定长数据类型,如果存放的数据未达到指定长度,会补空字符来填满,如类型CHAR(200)用来存放字符串"1"会花费200个字节,但启用行压缩后,会将填充的空字符移除,只需要1个字节便可以存放。而对于类型bit来说,除自身消耗的空间外,还需要额外的4个bit来存放元数据,因此也可以从行压缩中获益。


    行压缩影响的数据类型可参考http://msdn.microsoft.com/zh-cn/library/cc280576.aspx


    页压缩实现:
    页压缩是在行压缩的基础上进行前缀压缩,然后再进行字典压缩


    前缀压缩:前缀压缩针对页中的各列来进行压缩,首先从列中选取出一个前缀值(不要求页中每一行的该列的值都包含此前缀)存放在页头,然后使用该前缀替换页中每一行的该列值,如提起前缀为aabbcc,对应值aabbccdd则替换为6dd,对应值aadd则替换为2dd,对应值ccbbdd则替换成0ccbbdd,对应值aabbcc则替换成[],每行会生成一个前缀来处理。


    字典压缩:字典压缩是在前缀压缩完成后,搜索页面上任意位置的重复值,然后将它们存储在 CI 区域中。 与前缀压缩不同,字典压缩不局限于一列。 字典压缩可以替换页面上任意位置出现的重复值。


    当表和索引使用页压缩后,对于一个新的页面,插入数据行时会对该行启用行压缩,直到该页已满无法存放新增加的行时,才会使用页压缩的算法计算启用页压缩是否能存放新增加的行,如果可以存放,则对该页进行页压缩并将新增加的行放到该页,如果不能存放,则不对该页启用页压缩,申请新页来存放新行。


    在SQL SERVER 2012中,SQL Server 使用 Unicode 标准压缩方案 (Standard Compression Scheme for Unicode, SCSU) 算法实现来压缩在行或页压缩对象中存储的 Unicode 值。 对于这些压缩对象,Unicode 压缩对于 nchar(n) 和 nvarchar(n) 列而言是自动的。 数据库引擎 将 Unicode 数据存储为 2 个字节,无论区域设置如何。 这称为 UCS-2 编码。 对于某些区域设置而言,在 SQL Server 中实现 SCSU 压缩可节省高达 50% 的存储空间。

    数据压缩Demo

    复制代码
    --=============================================================================================================================
    --=========================================================
    --判断表和索引是否启用压缩和压缩类型
    --宋桑提供
    SELECT DISTINCT
    SCHEMA_NAME(o.schema_id)  + '.' + OBJECT_NAME(o.object_id) AS TableName,
    i.name AS IndexName,
    p.data_compression_desc AS CompressionType,
    i.type_desc AS StorageType
    FROM sys.partitions  p  with(nolock)
    INNER JOIN sys.objects o with(nolock)
    ON p.object_id = o.object_id 
    JOIN sys.indexes i 
    ON p.object_id = i.object_id
    AND i.index_id = p.index_id
    WHERE p.data_compression > 0 
    AND SCHEMA_NAME(o.schema_id) <> 'SYS' 
    
    
    --=========================================================
    --使用采样来预估数据对象启用压缩前后的空间使用
    --参考链接:http://msdn.microsoft.com/zh-cn/library/cc280574.aspx
    --PS:该算法只能起参考作用,数据压缩得到的空间可能比预估的要大很多
    EXEC sp_estimate_data_compression_savings 'dbo', 'TB', NULL, NULL, 'ROW' ;
    
    --=========================================================
    --对表使用数据压缩
    ALTER TABLE  <table_name>
    REBUILD PARTITION = ALL 
    WITH (DATA_COMPRESSION = PAGE|ROW)
    
    --=========================================================
    --对表中特定分区指定压缩
    ALTER TABLE <table_name> 
    REBUILD PARTITION = 1 WITH (DATA_COMPRESSION =  PAGE|ROW)
    
    --=========================================================
    --对表中多个特定分区指定压缩
    ALTER TABLE <table_name> 
    REBUILD PARTITION = ALL 
    WITH (DATA_COMPRESSION = PAGE ON PARTITIONS(<range>),
    ... )
    --=========================================================
    --在新建索引时指定压缩
    CREATE CLUSTERED INDEX [CLX_ID] ON [dbo].[TB2] 
    (
        [ID] ASC
    )WITH (DATA_COMPRESSION = { NONE | ROW | PAGE}) ON [PRIMARY]
    GO
    
    --=========================================================
    --使用重建索引来进行压缩
    ALTER INDEX [CLX_ID] ON [dbo].[TB2] REBUILD PARTITION = ALL 
    WITH ( DATA_COMPRESSION = { NONE | ROW | PAGE })
    
    
    --=============================================================================================================================
    复制代码


    压缩试验:
    压缩表定义为:

    复制代码
    CREATE TABLE [dbo].[TB1](
     [id] [bigint] IDENTITY(1,1) PRIMARY KEY,
     [star_uid] [bigint] NOT NULL,
     [source_uid] [bigint] NOT NULL,
     [site_type] [tinyint] NOT NULL,
     [site_server_type] [tinyint] NOT NULL,
     [site_id] [bigint] NOT NULL,
     [count] [int] NOT NULL,
     [create_date] [bigint] NOT NULL,
     ) ON [PRIMARY]
    复制代码


    压缩前占用空间:7309288KB
    压缩后占用空间:2594624KB
    压缩使用时间:3分58秒
    压缩环境:8Core 32G 4块SAS(15000转4盘片)做RAID 10

  • 相关阅读:
    【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine
    【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)
    【算法学习笔记】74. 枚举 状态压缩 填充方案 SJTU OJ 1391 畅畅的牙签袋(改)
    【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
    【算法学习笔记】72.LCS 最大公公子序列 动态规划 SJTU OJ 1065 小M的生物实验1
    【算法学习笔记】71.动态规划 双重条件 SJTU OJ 1124 我把助教团的平均智商拉低了
    【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
    【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
    【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
    【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
  • 原文地址:https://www.cnblogs.com/cuihongyu3503319/p/10270194.html
Copyright © 2011-2022 走看看