如何使用外部表和serde优化Hive查询

时间:2014-10-21 08:27:55

标签: hadoop indexing hive

第1部分:我的环境

我有以下文件上传到Hadoop:

  1. 是纯文本
  2. 每行包含JSON,如:
  3. {code:[int], customerId:[string], data:{[something more here]}}

    1. code是1到3000之间的数字,
    2. customerId总计高达4百万,每天高达0.5万
    3. 所有文件都是gzip
    4. 在配置单元中,我创建了带有自定义JSON serde的外部表(让我们称之为CUSTOMER_DATA)
    5. 每个date的所有文件都存储在单独的目录中 - 我将其用作Hive表中的分区
    6. 我所做的大多数查询都是按datecodecustomerId进行过滤。我还有第二个格式文件(让我们称之为CUSTOMER_ATTRIBUTES): [customerId] [attribute_1] [attribute_2] ... [attribute_n] 其中包含我所有客户的数据,因此行数最多为4百万。

      我按以下方式查询和过滤我的数据:

      1. date过滤 - 分区使用WHERE partitionDate IN (20141020,20141020)
      2. 完成此处的工作
      3. 使用{例如`WHERE code IN(1,4,5,33,6784)
      4. 之类的语句按code过滤
      5. CUSTOMER_ATTRIBUTESCUSTOMER_DATA一起加入条件查询,例如 SELECT customerId FROM CUSTOMER_DATA JOIN CUSTOMER_ATTRIBUTES ON (CUSTOMER_ATTRIBUTES.customerId=CUSTOMER_DATA.customerId) WHERE CUSTOMER_ATTRIBUTES.attribute_1=[something]
      6. 第2部分:问题

        有什么有效的方法可以优化我的查询。我读了索引和存储桶,我不知道我是否可以将它们与外部表一起使用,以及它们是否会优化我的查询。

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是最好的选择,可以进行很多优化。