第1部分:我的环境
我有以下文件上传到Hadoop:
{code:[int], customerId:[string], data:{[something more here]}}
code
是1到3000之间的数字,customerId
总计高达4百万,每天高达0.5万date
的所有文件都存储在单独的目录中 - 我将其用作Hive表中的分区我所做的大多数查询都是按date
,code
和customerId
进行过滤。我还有第二个格式文件(让我们称之为CUSTOMER_ATTRIBUTES):
[customerId] [attribute_1] [attribute_2] ... [attribute_n]
其中包含我所有客户的数据,因此行数最多为4百万。
我按以下方式查询和过滤我的数据:
date
过滤 - 分区使用WHERE partitionDate IN (20141020,20141020)
code
过滤
CUSTOMER_ATTRIBUTES
与CUSTOMER_DATA
一起加入条件查询,例如
SELECT customerId
FROM CUSTOMER_DATA
JOIN CUSTOMER_ATTRIBUTES ON (CUSTOMER_ATTRIBUTES.customerId=CUSTOMER_DATA.customerId)
WHERE CUSTOMER_ATTRIBUTES.attribute_1=[something]
第2部分:问题
有什么有效的方法可以优化我的查询。我读了索引和存储桶,我不知道我是否可以将它们与外部表一起使用,以及它们是否会优化我的查询。
答案 0 :(得分:5)
搜索效果:
就考虑性能而言,内部或外部表没有区别。您可以在两者上构建索引。在大型数据集上构建索引的任何一种方法都是反直觉的。
在搜索列上暂停数据会带来很多性能提升。但是,您是否可以提取数据取决于您的用例。 如果可以使用代码/客户ID,您可以考虑进行更多分区(如果可能)以获得更多收益。希望您不必拥有许多唯一代码或客户ID。
我强烈建议您远离JSON测试数据,而不是在Textual Json格式化数据上尝试这些内容。解析JSON(Text)是一个重要的性能杀手。
现在有很多文件格式都很好用。如果无法更改生成数据的组件,则可以使用一系列查询和表格转换为其他文件格式。这将是每个分区数据的一次性作业。之后,您的搜索查询将在较新的文件格式上运行得更快。
例如。 RC配置格式是由hive支持的。如果您将代码,customerid作为RCFILE中的单独列,则查询引擎可以完全跳过数据col,因为不匹配(1,4,5,33,6784)中的代码,从而大大减少了IO。 将数据存储在RCFile中,即柱状存储将有助于您的连接。使用RCFile运行带有连接的查询时,配置单元执行引擎将只读入所需的列,再次显着减少IO。除此之外,如果您将您的列作为JOIN键的一部分进行存储,则可以提高性能。
如果由于数据的嵌套性质而需要使用JSON,那么我建议您查看Parquet 它将为您提供RCFile +二进制(avro,thrift等)的性能提升
在我的工作中,我们有两列重度嵌套的JSON数据。我们尝试将其存储为压缩文本和序列文件格式。然后,我们将复杂的嵌套JSON列拆分为较少嵌套的多列,并将一些经常搜索的键拉出到其他列中。我们将其存储为RC文件,我们在搜索时观察到的性能提升很大。 右边有更多的数据突发,我们需要提高更多。在尝试了一些事情并与Cloudera家伙交谈后,只有一个很大的领域需要改进。远离JSON解析。实木复合地似乎是空闲的候选人。
答案 1 :(得分:2)
是的,您可以将索引与外部表一起使用。索引会优化搜索查询。
CREATE INDEX your_index_name ON TABLE your_table_name(field_you_want_to_index) AS 'COMPACT' WITH DEFERRED REBUILD;
索引会占用大量数据集的大量时间,因此我们可以进行延迟重建,即在生产时间之后:)
ALTER INDEX your_index_name ON your_table_name REBUILD;
您甚至可以重建特定分区。
ALTER INDEX your_index_name ON your_table_name PARTITION(your_field = 'any_thing') REBUILD;
当你加入两个表时,BUCKETING是最好的选择,可以进行很多优化。