
# 配置HBase数据压缩格式和编码
#### 操作场景
在HBase数据存储场景中，管理员需要优化存储空间和读写性能。HBase提供两种数据压缩方式：data block encoding和压缩算法。data block encoding通过减少Key-Value中Key的重复部分来压缩数据，目前支持NONE、PREFIX、DIFF、FAST_DIFF和ROW_INDEX_V1编码方式，其中NONE表示不使用编码。压缩算法对HFile文件进行整体压缩，默认支持NONE、GZ和SNAPPY三种算法，其中NONE表示HFile不压缩。这两种方式都作用在HBase的列簇上，可以同时使用，也可以单独使用。合理选择编码方式和压缩算法，可以在存储空间和读写性能之间取得平衡。本文介绍如何配置HBase数据压缩格式和编码。
- **Data Block Encoding**：HBase提供的数据编码方式，通过减少Key-Value中Key的重复部分来压缩数据。编码方式作用于HFile的data block，在数据写入时进行编码，读取时进行解码。编码方式对CPU消耗较小，适合对读写性能要求高的场景。
- **压缩算法**：HBase提供的数据压缩方式，对HFile文件进行整体压缩。压缩算法在数据写入时进行压缩，读取时进行解压。压缩算法对CPU消耗较大，但压缩率更高，适合对存储空间要求高的场景。
- **Compaction**：HBase的后台合并操作，将多个小的HFile合并为一个大的HFile。修改列簇的压缩格式或编码方式后，已有的HFile需要在下次compaction完成后才会生效。
- **HFile**：HBase的底层存储文件格式，采用LSM-Tree结构，数据按RowKey有序排列。HFile由多个data block组成，每个data block包含若干Key-Value对。
 
#### 前提条件
- 已安装HBase客户端。例如，客户端安装目录为"/opt/client"。
- 如果集群开启了Kerberos认证，操作的用户还需要具备对应的操作权限。即创建表时需要具备对应的namespace或更高级别的创建（C）或者管理（A）权限，修改表时需要具备已创建的表或者更高级别的创建（C）或者管理（A）权限。具体的授权操作请参考[创建HBase用户并绑定角色](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_1608.html)章节。
 
#### 配置HBase数据压缩格式和编码
**创建表时设置data block encoding和压缩算法。**
- **方法一：使用hbase shell** 。
  1. 以客户端安装用户，登录安装客户端的节点。
  
  2. 执行以下命令切换到客户端目录。
     ```
     cd /opt/client
     ```
     
  
  3. 执行以下命令配置环境变量。
     ```
     source bigdata_env
     ```
     
  
  4. 如果当前集群已启用Kerberos认证（安全模式），执行以下命令认证当前用户。如果当前集群未启用Kerberos认证（普通模式），则无需执行此命令。
     ```
     kinit 组件业务用户
     ```
     例如：
     ```
     kinit hbaseuser
     ```
     
  
  5. 执行以下命令登录HBase客户端：
     ```
     hbase shell
     ```
     
  
  6. 执行以下命令创建表：
     ```
     create 't1', {NAME => 'f1', COMPRESSION => 'SNAPPY', DATA_BLOCK_ENCODING => 'FAST_DIFF'}
     ```
     其中：
     - t1：表示表名。
     
     - f1：表示列簇名。
     
     - SNAPPY：表示该列簇使用的压缩算法为"SNAPPY"。
     
     - FAST_DIFF：表示使用的编码方式为"FAST_DIFF"。
     
     - **{}** 内的参数为指定列簇的参数，多个列簇可以用多个**{}** 并用逗号隔开。关于建表语句的更多使用说明可以在**hbase shell** 中执行以下命令进行查看：
       ```
       help 'create'
       ```
       
      
  
  7. 执行以下命令查看表属性：
     ```
     desc '表名'
     ```
     回显结果中会显示编码方式及压缩算法信息，例如：
     图1查看表信息   
     ![](https://support.huaweicloud.com/cmpntguide-lts-mrs/zh-cn_image_0000002500902092.png "点击放大") 
   
- **方法二：使用Java API** 。
  以下代码片段仅展示如何在建表时设置列簇的编码和压缩方式，完整的建表代码以及如何通过代码建表请参考HBase开发指南的[创建HBase表](https://support.huaweicloud.com/devg-lts-mrs/mrs_07_080017.html)章节。
  ```
  TableDescriptorBuilder htd = TableDescriptorBuilder.newBuilder(TableName.valueOf("t1"));// 创建t1表的descriptor.
  ColumnFamilyDescriptorBuilder hcd = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("f1"));//  创建列簇f1的builder.
  hcd.setDataBlockEncoding(DataBlockEncoding.FAST_DIFF);// 设置列簇f1的编码方式为FAST_DIFF. 
  hcd.setCompressionType(Compression.Algorithm.SNAPPY);// 设置列簇f1的压缩算法为SNAPPY
  htd.setColumnFamily(hcd.build())// 将列簇f1添加到t1表的descriptor.
  ```
  
**对已存在的表** **设置或修改data block encoding和压缩算法**。
- **方法一：使用hbase shel** **l** 。
  1. 以客户端安装用户，登录安装客户端的节点。
  
  2. 执行以下命令切换到客户端目录。
     ```
     cd /opt/client
     ```
     
  
  3. 执行以下命令配置环境变量。
     ```
     source bigdata_env
     ```
     
  
  4. 如果当前集群已启用Kerberos认证（安全模式），执行以下命令认证当前用户。如果当前集群未启用Kerberos认证（普通模式），则无需执行此命令。
     ```
     kinit 组件业务用户
     ```
     例如：
     ```
     kinit hbaseuser
     ```
     
  
  5. 执行以下命令登录HBase客户端：
     ```
     hbase shell
     ```
     
  
  6. 执行以下命令修改HBase表：
     ```
     alter 't1', {NAME => 'f1', COMPRESSION => 'SNAPPY', DATA_BLOCK_ENCODING => 'FAST_DIFF'}
     ```
     
   
- **方法二：使用Java API** 。
  以下代码片段仅展示如何修改指定表的已有列簇的编码和压缩方式，完整的修改表代码以及如何通过代码修改表请参考HBase应用开发指南的[修改HBase表](https://support.huaweicloud.com/devg-lts-mrs/mrs_07_080019.html)章节：
  ```
  TableDescriptor htd = admin.getDescriptor(TableName.valueOf("t1"));// 获取表t1的descriptor
  ColumnFamilyDescriptor originCF = htd.getColumnFamily(Bytes.toBytes("f1"));// 获取列簇f1的descriptor
  builder.ColumnFamilyDescriptorBuilder hcd = ColumnFamilyDescriptorBuilder.newBuilder(originCF);// 通过已有的列簇属性构造一个builder
  hcd.setDataBlockEncoding(DataBlockEncoding.FAST_DIFF);// 重新设置列簇的编码方式为FAST_DIFF
  hcd.setCompressionType(Compression.Algorithm.SNAPPY);// 重新设置列簇的压缩算法为SNAPPY
  admin.modifyColumnFamily(TableName.valueOf("t1"), hcd.build());// 提交到服务端修改列簇f1的属性
  ```
  修改后完成后，已有的HFile的编码和压缩方式需要在下次做完compaction后才会生效。
  
**验证操作：**
配置完成后，可通过以下方式验证压缩格式和编码方式是否生效：
1. 在hbase shell中执行**desc** *'表名'*命令，查看表的列簇属性，确认COMPRESSION和DATA_BLOCK_ENCODING参数已正确设置。
2. 向表中写入数据，等待compaction完成后，通过HDFS命令查看HFile文件大小，确认数据已被压缩。
 
#### 常见问题
- **如何选择合适的编码方式和压缩算法**
  不同的编码方式和压缩算法在压缩率、CPU消耗、读写性能方面各有特点，需要根据业务场景选择。
  如果对读写性能要求高，建议选择FAST_DIFF编码方式，对CPU消耗小。如果对存储空间要求高，建议选择SNAPPY压缩算法，压缩率较高且压缩速度较快。如果Key重复度高，可以选择PREFIX或DIFF编码。一般情况下，建议同时使用FAST_DIFF编码和SNAPPY压缩算法，在性能和存储空间之间取得平衡。
  
- **修改压缩格式后未生效**
  修改列簇的压缩格式或编码方式后，已有的HFile仍使用原有的压缩格式，只有在新写入数据或compaction后生成的HFile才会使用新的压缩格式。
  等待compaction完成，或手动触发major compaction强制合并所有HFile，使新的压缩格式生效。
  
 
#### 相关文档
- 了解HBase日志介绍，请参考[HBase日志介绍](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_1056.html)。
- 了解HBase性能调优，请参考[HBase性能调优](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_1013.html)。
- 了解HBase常见问题，请参考[HBase常见问题](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_1638.html)。
 
