【问题标题】:Read Hive partitioned from S3 into Spark将从 S3 分区的 Hive 读入 Spark
【发布时间】:2016-04-02 08:50:31
【问题描述】:

在使用 Hive EMR 一段时间后,我正在迈出使用 Spark 的第一步。

我想读取以以下格式保存到 S3 的 Hive 表:
s3://<bucket>/<rootpath>/date=<date>/fileNames

我可以使用答案in this question,但随后我失去了 dataRows 与date 之间的连接,这是因为我没有将日期保存在文件中。

有没有一种简单的方法来获得每一行数据的文件名?

【问题讨论】:

    标签: java hadoop amazon-web-services amazon-s3 apache-spark


    【解决方案1】:

    如果您从文件名中需要的只是听起来的日期,那么您不需要将文件名作为 spark 获取,并且如果您正确创建表,hive 会自动为您执行此操作。让我演示一下:

    # in hive
    hive> create table t1 ( name string) partitioned by  (date string) STORED AS TEXTFILE LOCATION 'your s3 path';
    # data.txt contains 'john' and 'jay' in two different lines
    hive> load data local inpath 'data.txt' into table t1 PARTITION(date='2015-12-30');
    hive> select * from t1;
    OK
    john    2015-12-30
    jay 2015-12-30
    # in spark-shell
    scala> sqlContext.sql("select * from t1").foreach(println);
    [john,2015-12-30]
    [jay,2015-12-30]
    

    我认为这是你想要的。它的另一个优点是您的数据可以在查询时利用分区的性能优势。

    【讨论】:

    • 不太清楚如何在 Java 上实现它。
    • 哪一部分?创建表只是一个 hive 查询,要添加所有现有分区,您只需发出“ALTER TABLE yourtable RECOVER PARTITIONS”。之后你就可以正常使用你的桌子了。以上都不是特定于scala的。
    【解决方案2】:

    您可以使用 wholeTextFiles 来读取 rdd。这将读取每个文件,文件名作为键,文件的全部内容作为值。从那里,您应该能够使用 flatMapValues 将每条记录分成自己的 k/v 对。

    val input = sc.wholeTextFiles(s3://...)
    val inputFlat = input.flatMapValues(line => line.split("\n"))
    

    对于这个例子,如果你的路径是 /user/hive/date=December/part-0000 并且 part-0000 的内容是

    Joe December-28 Something
    Ryan December-29 AnotherThing
    

    输出如下所示:

    input.take(1)
    (/user/hive/date=December/part-0000, Joe December-28 Something\n Ryan December-29 AnotherThing)
    
    inputFlat.take(2)
    (/user/hive/date=December/part-0000, Joe December-28 Something)
    (/user/hive/date=December/part-0000, Ryan December-29 AnotherThing)
    

    我想您可以尝试以下方法。读取记录会有点慢,但是重新分区后可以最大化并行处理

    inputFlat.flatMapValues(//some split).repartition(numWorkers)
    

    我们可以尝试的另一件事是使用它: 在 hive 中,您可以使用名为 INPUT__FILE__NAME 的虚拟列检索找到记录的文件,例如:

    select INPUT__FILE__NAME, id, name from users where ...;
    

    我不确定它是否会起作用,但您可以尝试在您的 .sql api 中使用它。您必须确保您的 sqlContext 具有 hive-site.xml。

    【讨论】:

    • 谢谢,但是对于非常大的文件(每个大约 1Gb),这是否是一个有效的解决方案?
    • 不,那是个坏主意,因为那时您只能让一个内核处理一个文件。
    • 你有解决这个问题的方法吗?我遇到了同样的问题,不知道如何继续
    猜你喜欢
    • 2019-02-16
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    • 1970-01-01
    • 2020-02-06
    • 2019-10-27
    • 1970-01-01
    • 2020-01-06
    相关资源
    最近更新 更多