原文towardsdatascience.com/must-know-techniques-for-handling-big-data-in-hive-fa70e020141dhttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8e9346e3b89821d60f53b5e7dab035a0.png图片由 Christopher Gower 在 Unsplash 上提供在大多数科技公司中数据团队必须具备强大的管理和处理大数据的能力。因此对这些团队来说熟悉 Hadoop 生态系统是必不可少的。Apache 开发的 Hive 查询语言HQL是数据专业人士在 Hadoop 生态系统中操纵、查询、转换和分析数据的强大工具。HQL 提供了一个类似 SQL 的接口使得在 Hadoop 中进行数据处理对广泛的用户既易于访问又用户友好。如果你已经精通 SQL你可能会发现过渡到 HQL 并不困难。然而需要注意的是HQL 包含许多独特的函数和特性这些在标准 SQL 中是不可用的。在这篇文章中我将根据我的先前经验探讨一些关键的 HQL 函数和特性这些需要超出 SQL 的特定知识。理解和利用这些能力对于任何使用 Hive 和大数据的人来说至关重要因为它们构成了在 Hadoop 生态系统中构建可扩展和高效数据处理管道和分析系统的基石。为了说明这些概念我将提供带有模拟数据和相应的 HQL 语法的用例以展示如何有效地应用这些特性。PARTITIONED BY让我们想象一家电子商务公司需要每天更新其销售数据。如果所有数据都存储在一个未分区的单一数据集中几个月后表可能会变得非常大这会显著降低查询性能。Apache Hive 使用PARTITIONED BY子句来创建分区表允许查询跳过无关的数据子集从而提高效率。在这个例子中我首先创建了一个名为ecom_sales的表该表包括SKU_id列——每个 SKU 的唯一标识符units_sold列——特定 SKU 的销售单位数以及price_USD列——每单位的价格。该表还包括一个分区列ymd。接下来我在ymd 20240801的分区中插入值。最后我查询了这个分区中的所有数据。--Create a partitioned tableforsales CREATE TABLE IF NOT EXISTS ecom_sales(SKU_id STRING,unit_sold INT,price_USD DOUBLE)PARTITIONED BY(ymd INT)STORED AS PARQUET;--Insert data into the partitioned table dated August 1st,2024INSERT INTO ecom_sales PARTITION(ymd20240801)VALUES(S0002D,5,15.99),(S0002D,6,15.99),(S0001D,12,7.99),(S0003D,10,21.50),(S0001D,9,7.99),(S0001D,10,7.99);--Queryalldatafromthe partition table dated August 1st,2024SELECT*FROM ecom_sales WHERE ymd20240801;在 Hive 中分区无疑通过避免全表扫描来提高查询速度。它还使得定位和修改特定记录变得更加容易。通过分区你可以通过在非重叠分区上运行操作如UPDATE和DELETE来防止并发问题。然而对小文件问题保持谨慎是很重要的。最好是创建 100 个每个 1GB 的分区而不是 10,000 个每个 0.01GB 的分区。小文件可能会引起几个问题·查询性能降低大量分区会增加 Hive 元数据处理的负担从而减慢查询规划和执行速度。Hadoop 的分布式处理针对大文件进行了优化而小文件可能导致过度的磁盘 I/O、网络开销和不必要的 MapReduce 任务。·浪费的存储空间在 HDFS 中每个文件无论其大小如何都占用一个完整的存储块通常是 128 MB 或 256 MB。小文件会导致存储空间使用效率低下。·管理挑战管理大量小文件会使得优化、数据合并、压缩和平衡等任务变得复杂使得维护更加困难。存储为Hive 使用STORED AS子句来指定表存储的文件格式。文件格式的选择可以显著影响查询性能和存储效率。在前面的PARTITIONED BY子句部分我创建了一个名为ecom_sales的分区表并存储为 PARQUET 格式。--Create a partitioned tableforsaleswithfileformatPARQUET CREATE TABLE IF NOT EXISTS ecom_sales(SKU_id STRING,unit_sold INT,price_USD DOUBLE)PARTITIONED BY(ymd INT)STORED AS PARQUET;除了 PARQUET 之外Hive 还支持几种其他文件格式PARQUET一种针对分析工作负载和复杂查询优化的列式存储格式。ORC优化行列式由于其高压缩率和快速的读写性能非常适合写密集型工作负载和事务处理。AVRO一种基于行的格式支持结构化和非结构化数据使其适合于模式演变。TEXTFILE用于纯文本的格式通常用于 CSV 或 TSV 文件。如果没有指定它是默认格式。JSONFILE用于存储 JSON 格式的数据。除了这五种常用的格式之外Hive 还支持其他格式例如SEQUENCEFILE由二进制键/值对组成的平面文件RCFILE记录列式文件INPUTFORMAT和OUTPUTFORMAT用于自定义文件格式和可指定压缩的压缩格式。在 Hive 中创建新表时选择适当的格式对于确保高效的数据摄取、存储、查询和处理至关重要。分布 BY / 聚合 BYHive 使用 DISTRIBUTE BY 子句将行分布到 reducer 中。SET mapreduce.job.reduces2;SELECT*FROM ecom_sales WHERE ymd20240801DISTRIBUTE by SKU_id;在上面的示例中我将 reducer 的数量设置为 2。在应用DISTRIBUTE BY子句后所有具有相同SKU_id的行将由同一个 reducer 处理而不同的SKU_id值可能会被发送到不同的 reducer。例如具有SKU_idS0001D的行将进入一个 reducerS0002D进入另一个 reducer而‘S0003D’进入另一个。S0001D和S0002D最终是否在同一个或不同的 reducer 上取决于 Hive 使用的哈希函数。您还可以将SORT BY子句添加到语法中它将在每个 reducer 内部对数据进行排序。SET mapreduce.job.reduces2;SELECT*FROM ecom_sales WHERE ymd20240801DISTRIBUTE BY SKU_id SORT BY SKU_id;结果将如下所示https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3a781860799ccd19b57f7f09000c5413.png作者图片或者您可以使用CLUSTER BY来结合DISTRIBUTE BY和SORT BY的功能产生相同的输出。SET mapreduce.job.reduces2;SELECT*FROM ecom_sales WHERE ymd20240801CLUSTER BY SKU_id;LATERAL VIEW 与 EXPLODELATERAL VIEW 与 EXPLODE 函数的组合是 Hive 处理数组或映射数据类型的一个强大功能。它允许您将嵌套数据结构扁平化到更传统的关联格式中使得分析复杂数据更加容易。为了演示这个功能我创建了一个名为products的另一个表具有以下列SKU_id——每个 SKU 的唯一标识符SKU_name——与 SKU 关联的产品名称以及description——包含该 SKU 产品描述的数组。CREATE TABLE products(SKU_id STRING,SKU_name STRING,description ARRAYSTRING);INSERT INTO products VALUES(S0001D,white_shirt_small,ARRAY(shirt,white,small)),(S0002D,blue_pants_large,ARRAY(pants,blue,large)),(S0003D,yellow_jacket_large,ARRAY(pants,blue,large));SELECT*FROM products;上面的语法创建了一个看起来像的表https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/86f534343845ed4676ad670bddc9a219.png图片由作者提供接下来我使用 EXPLODE 函数将数组description分解成单独的行其中数组的每个元素都成为单独的行。然后使用 LATERAL VIEW 为原始products表中的数组生成的每一行创建一个虚拟表名为featureTable。SELECT p.SKU_id,p.SKU_name,feature FROM products p LATERAL VIEW EXPLODE(p.description)featureTable AS feature;查询结果将看起来像https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/fa054f4ee2e464ef5f4f6fa06de2693c.png图片由作者提供COLLECT_SETCOLLECT_SET 函数是 Hive 中的一个聚合函数它将唯一元素收集到一个数组中有效地执行了LATERAL VIEW与EXPLODE函数的逆操作。下面的语法创建了一个名为prod_features的表其中特定元素将被分组到数组中。CREATE TABLE prod_features(SKU_id STRING,SKU_name STRING,feature STRING);INSERT INTO prod_features VALUES(S0001D,white_shirt_small,shirt),(S0001D,white_shirt_small,white),(S0001D,white_shirt_small,small),(S0002D,blue_pants_large,pants),(S0002D,blue_pants_large,blue),(S0002D,blue_pants_large,large),(S0003D,yellow_jacket_large,jacket),(S0003D,yellow_jacket_large,blue),(S0003D,yellow_jacket_large,large);SELECT*FROM prod_features;https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/178589efbc80238c1bf2ce5fe4142ed8.pngprod_features图片由作者提供以下语法演示了 COLLECT_SET 函数如何将feature列中的所有唯一值聚合到一个数组中。SELECT SKU_id,SKU_name,COLLECT_SET(feature)AS description FROM prod_features GROUP BY SKU_id,SKU_name;查询结果将显示为https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/701345d5d3cb9203683cd41f780eafd5.png图片由作者提供结论本文讨论了 5 个 Hive 特定功能这些功能使 Hive 与 SQL 不同使其特别适合大数据处理和分析。PARTITIONED BY通过优化数据存储和检索使大型数据集的管理更加高效。存储为通过使用针对工作负载定制的特定文件格式提高了存储效率和查询性能。DISTRIBUTE BY和CLUSTER BY对于分布式系统中的数据查询性能优化至关重要因为它们在并行处理期间对 reducer 上数据分布的粒度控制。LATERAL VIEW 与 EXPLODE将数组或映射数据类型转换为单独的行便于对嵌套数据结构进行详细分析。COLLECT_SET将单个元素聚合到数组中为汇总和分组数据提供了强大的工具。通过利用这些 Hive 特定的功能数据专业人员可以建立更有效和健壮的大数据解决方案解决仅使用标准 SQL 难以或无法应对的挑战。