我知道当您创建 ORC 表时,它会显着提高速度。但是,我们可以通过对 ORC 表进行分区和分桶来进一步改进它吗?如果是这样,如何在现有的 ORC 表中进行分区和分桶?
2 回答
您可以对 ORC 表进行存储和分区。
分区直接映射到 HDFS 中的目录。您可以 ALTER TABLE 并添加分区。你必须在你之后进行分区恢复。一切都在这里得到很好的解释:https ://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-AlterPartition 。
就我个人而言,我会使用动态分区创建新表并将数据复制到新表中。
分区和分桶是提供帮助提高查询性能的功能。在 Hive 中,正如 Karol 所解释的,分区映射到 hdfs 目录结构,分区方式完全由查询需求和模式驱动。例如
customer_purchases 表存储过去 2-3 年的所有交易(大约 1-2 PB 的数据)。一位分析师试图回答“2017 年第一季度每月发生了多少销售额?”。
无分区
customer_purchases 表架构
交易ID | cust_id | 每单位价格 | units_purchased | 发票日期
样本数据集
1,CustomerId-32,3.24,91,2017-10-19
2,CustomerId-16,3.24,88,2017-10-14
3,CustomerId-3,1.96,99,2017-10-14
4,CustomerId-95,1.96,38,2017-10-17
5,CustomerId-51,1.32,39,2017-10-18
6,CustomerId-29,1.32,14,2017-10-14
7,CustomerId-15,3.88,66,2017-10-19
8,CustomerId-74,1.32,44,2017-10-17
9,CustomerId-43,3.88,22,2017-10-18
Stored as csvs in hdfs://your-nn/your-path/data*.csv
SELECT month(invoiceDate), count(*) FROM customer_purchases WHERE YEAR(invoiceDate) = '2017' AND MONTH(invoiceDate) BETWEEN 1 AND 3 GROUP BY MONTH(invoiceDate)
上面的语句会进行整个表扫描以执行过滤器(where)和聚合(group by)。这是低效的,因为我们只需要一小部分数据集。
带分区
我们可以推断该分区更多地基于时间序列,因为存在日期范围。为了避免全表扫描,我们可以创建一个基于月份的分区。以下是变化
customer_purchases 表模式(分区列 'yr' 和 'mon')
交易ID | cust_id | 每单位价格 | units_purchased | 发票日期 | 星期一
相同的数据以 hdfs://your-nn/your-path///data*.csv 形式存储在 hdfs 中,其中 yyyy 格式的年份是 1 到 12 之间的任何值(1 月到 12 月)。
使用新的 hdfs 结构和 hive 表模式结构。查询将是
SELECT mon, count(*) FROM customer_purchases WHERE yr='2017' AND mon BETWEEN 1 AND 3 GROUP BY mon
上述查询的解释计划现在将仅扫描 yr=2017 目录和 mon=1、mon=2 和 mon=3 子目录下的文件。这是一个小数据集,您将更快地返回结果。
根据 ORC 文件格式,除了 hdfs 位置中的文件将是 .orc 而不是 .csv 之外,没有什么会改变。
BUCKETING 添加了对特定文件中的事务进行分组。
这是否回答你的问题?
动态分区有助于根据表中的输入事务数据自动执行分区。