(译)优化ORC和Parquet文件,提升大SQL读取性能

时间秒杀一切 提交于 2019-11-30 17:58:10

本文编译自IBM开发者社区,主要介绍了HDFS中小的ORCParquet文件的问题,以及这些小文件如何影响Big SQL的读取性能,并探索了为了提高读取性能,使用现有工具将小文件压缩为大文件的可能解决方案。

简介

众所周知,多个Hadoop小文件(定义为明显小于HDFS块大小的文件,默认情况下为64MB)是Hadoop分布式文件系统(HDFS)中的一个大问题。HDFS旨在存储大量数据,理想情况下以大文件的形式存储。在HDFS中存储大量小文件,而不是存储较少的大文件,这在管理文件的目录树时给NameNode增加了额外的开销。此外,MapReduce和其他读取HDFS文件的作业也会受到负面影响,因为它将涉及与HDFS的更多通信以获取文件信息。

小文件读取性能问题对于存储格式更为严重,在存储格式中,元数据被嵌入文件中以描述所存储的复杂内容。IBM Db2 Big SQL使用的两种常见文件存储格式是ORCParquet,这些文件格式以列格式存储数据,以优化读取和过滤列的子集。ORCParquet格式将有关列和行组的信息编码到文件本身中,因此,在对文件中的数据进行解压缩、反序列化和读取之前,需要处理元数据。由于这种开销,处理以逻辑方式捆绑在一起的这些格式的多个小型文件(例如,属于Big SQL表或分区的文件)会产生大量成本,并降低IBM Db2 Big SQL的读取性能。

建议解决方案:压缩

避免在存储级别使用小文件的一个好习惯是对逻辑上属于一起的目录里的小文件进行压缩。在Big SQL中,属于同一表的文件通常存储在同一目录中。IBM Db2 Big SQL的“文件检查工具”有助于识别HDFS中有问题的小文件,并提供文件压缩建议。将这些文件合并为更大的文件,会最大程度地减少要处理的元数据并更有效地将文件大小与HDFS块对齐,有助于提高Big SQL读取性能。

ORCParquet提供了它们自己的不同工具来进行文件合并或压缩:

  • ORC使用HIVE DDL
  • Parquet使用工具执行合并命令

ORC文件合并

使用Hive DDLHive Data Definition Language),用户可以通过在表或分区上执行concatenate命令来有效地合并小文件为更大的文件,命令如下:

ALTER TABLE table_name [PARTITION (partition_key = 'partition_value')] CONCATENATE;

Hive会在stripe级别合并ORC文件来降低数据压缩/解压和编解码的开销。

Parquet文件合并

作为Apache Parquet项目的一部分,有一组基于Java的命令行工具,称为parquet-tools。最新的parquet-tools版本包括一个merge命令,该命令可以将较小的parquet文件逻辑地追加到较大的parquet文件中。该命令以二进制形式将parquet文件块串联在一起,而无需序列化/反序列化、合并页脚、修改路径和偏移量元数据。

要在HDFS中运行parquet-tools merge命令:

hadoop jar parquet-tools-1.9.0.jar merge <input> <output>

其中,input是源parquet文件或目录,而output是合并原始内容的目标parquet文件,此合并命令不会删除或覆盖原始文件。因此,它需要手动创建一个临时目录,并用压缩后的文件替换原始的小文件,以使Big SQLApache Hive知道该文件。

另外,不管文件的存储格式如何,要考虑的解决方案是重新创建表并通过执行INSERT…SELECT进行压缩。

使用INSERT…SELECT合并文件

通过使用INSERT…SELECT语法直接创建一个新表作为原始表的副本来压缩效率低下的拆分数据,此过程将根据插入的并行度将数据重新组织为相对少量的较大文件。

以下是一个如何创建新表,然后在Big SQL中插入旧表中的数据的示例:

CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table select * from old_table;

该解决方案还允许通过将数据分区复制到新表中,删除原始分区并插入新的压缩分区来合并单个分区中的文件。

最后,如果需要保留小文件以供记录,建议使用Hadoop存档资源(Hadoop Archive Resources (har))对其进行存档,降低NameNode管理大量资源和对象的成本。

性能改进

内部测试表明,压缩ORCParquet小文件有助于显著提高Big SQL的读取性能。

针对ORCParquet格式进行测试的方案包括:

一百万行表以两种方式存储:

  • HDFS中30个大小不一的非最佳小文件
  • HDFS中的2个压缩大文件,是根据文件格式使用parquet toolsHive DDL合并的小文件的结果

运行一个查询,计算一个数字列的总和,以通过访问所有列内容来给整个表施加压力:

SELECT SUM(column_name) FROM table_name;

结果表明:

  • ORC格式的非压缩表运行查询比在压缩表上运行查询多2倍的时间
  • parquet格式的非压缩表运行查询比在压缩表上运行查询多1.6倍的时间

这是针对ORC文件格式的压缩测试的输出,其中SLS_SALES_FACT_ORC是非压缩表,而SLS_SALES_FACT_COMPACTED_ORC是在非压缩表上运行CONCATENATE命令的表结果:

[host][bigsql] 1> SELECT COUNT(*) FROM GOSALESDW.SLS_SALES_FACT_ORC;
+---------+
| 1       |
+---------+
| 1000000 |
+---------+
1 row in results(first row: 0.393s; total: 0.395s)

[host][bigsql] 1> SELECT SUM(GROSS_PROFIT) FROM GOSALESDW.SLS_SALES_FACT_ORC;
WARN [State: 01003][Code: 0]: Statement processing was successful.. SQLCODE=0, SQLSTATE=01003, DRIVER=3.72.24
+------------------+
| 1                |
+------------------+
| 4615167406.55999 |
+------------------+
1 row in results(total: 7.681s)

[bigsql@host root]$ hdfs dfs -ls /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc
Found 30 items
drwxrwxrwx - bigsql hadoop 0 2017-12-14 17:54 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/._biginsights_stats
-rw-r--r-- 3 bigsql hadoop 443027 2017-12-14 17:53 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_-307213540_201712140553882_1.1
-rw-r--r-- 3 bigsql hadoop 179411 2017-12-14 17:53 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_-307213540_201712140553882_1.2
-rw-r--r-- 3 bigsql hadoop 897796 2017-12-14 17:49 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_-412191103_201712140549330_1.1
-rw-r--r-- 3 bigsql hadoop 1176528 2017-12-14 17:49 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_-412191103_201712140549330_1.2
-rw-r--r-- 3 bigsql hadoop 3356 2017-12-14 17:59 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_-710448882_201712140559369_1.1

...
-rw-r--r-- 3 bigsql hadoop 52854 2017-12-14 18:09 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_-451786036_201712140609603_2.2
-rw-r--r-- 3 bigsql hadoop 435203 2017-12-14 18:09 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_215889957_201712140609092_1.1
-rw-r--r-- 3 bigsql hadoop 1218285 2017-12-14 18:09 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_215889957_201712140609092_1.2
-rw-r--r-- 3 bigsql hadoop 2112684 2017-12-14 17:51 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_orc/i_1512166475533_866891040_201712140551232_2.2

[host][bigsql] 1> SELECT COUNT(*) FROM GOSALESDW.SLS_SALES_FACT_COMPACTED_ORC;
+---------+
| 1       |
+---------+
| 1000000 |
+---------+
1 row in results(first row: 0.379s; total: 0.381s)

[host][bigsql] 1> SELECT SUM(GROSS_PROFIT) FROM GOSALESDW.SLS_SALES_FACT_COMPACTED_ORC;
WARN [State: 01003][Code: 0]: Statement processing was successful.. SQLCODE=0, SQLSTATE=01003, DRIVER=3.72.24
+------------------+
| 1                |
+------------------+
| 4615167406.55999 |
+------------------+
1 row in results(total: 3.673 s)

[bigsql@host root]$ hdfs dfs -ls /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_compacted_orc
Found 3 items
drwxrwxrwx - bigsql hadoop 0 2017-12-14 18:14 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_compacted_orc/._biginsights_stats
-rwxrwxrwx 3 bigsql hadoop 19602272 2017-12-15 12:19 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_compacted_orc/000000_0
-rwxrwxrwx 3 bigsql hadoop 3720403 2017-12-15 12:19 /apps/hive/warehouse/gosalesdw.db/sls_sales_fact_compacted_orc/000001_0

注意:这些测试使用单个数据集来测量压缩表的性能,我们建议您在运行文件压缩之前测试自己的基准,并研究该操作带来的性能优势。

需要注意的

建议对上述存储格式的文件脱机运行修改操作,真正的问题是写入或删除文件的操作如何不影响当前正在运行并访问旧文件的查询任务,压缩文件本身并不复杂,但是不影响正在使用文件的任务可能会成为问题。

此外,表信息存储在Big SQL以及Hive Metastore中,该信息包含与表关联的实际文件的详细信息。使用Parquet工具压缩文件时,至少需要更新Hive Metastore以反映新文件。Big SQL具有在Hive Metastore中拉取更改并将其传播到其自己的catalog中的逻辑。

参考资料

编译自:Optimizing ORC and Parquet files for Big SQL queries performance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!