在Azure Databricks中读取日期范围之间的镶木地板文件的有效方法

时间:2019-02-28 16:39:08

标签: azure-data-lake databricks azure-databricks

我想知道下面的伪代码是否是从PySpark(Azure Databricks)读取存储在Azure Data Lake中的日期范围之间的多个实木复合地板文件的有效方法。注意:实木复合地板文件不会按日期分区。

我正在使用uat / EntityName / 2019/01/01 / EntityName_2019_01_01_HHMMSS.parquet约定将数据存储在ADL中,如Nathan Marz在《大数据》一书中所建议的那样,进行了一些修改(使用2019而不是year = 2019)。

使用*通配符读取所有数据:

df = spark.read.parquet(uat/EntityName/*/*/*/*)

添加一个列FileTimestamp,该列使用字符串操作并转换为TimestampType()从EntityName_2019_01_01_HHMMSS.parquet中提取时间戳。

df.withColumn(add timestamp column)

使用过滤器获取相关数据:

start_date = '2018-12-15 00:00:00'
end_date = '2019-02-15 00:00:00'
df.filter(df.FileTimestamp >= start_date).filter(df.FileTimestamp < end_date)

基本上,我正在使用PySpark模拟U-SQL中可用的简洁语法:

@rs = 
  EXTRACT 
      user    string,
      id      string,
      __date  DateTime
  FROM 
    "/input/data-{__date:yyyy}-{__date:MM}-{__date:dd}.csv"
  USING Extractors.Csv();

@rs = 
  SELECT * 
  FROM @rs
  WHERE 
    date >= System.DateTime.Parse("2016/1/1") AND
    date < System.DateTime.Parse("2016/2/1");

1 个答案:

答案 0 :(得分:0)

对数据进行分区的正确方法是在数据上使用year = 2019,month = 01等形式。

使用诸如以下的过滤器查询此数据时:

df.filter(df.year >= myYear)

然后,Spark将只读取相关的文件夹。

非常重要的一点是,过滤列名称必须准确显示在文件夹名称中。请注意,当您使用Spark写入分区数据(例如按年,月,日)时,它不会将分区列写入镶木地板文件中。而是从路径中推断出它们。这确实意味着您的数据框在编写时会需要它们。从分区源中读取它们时,它们也将作为列返回。

如果您无法更改文件夹结构,则可以始终手动减少文件夹以供Spark使用正则表达式或Glob读取-本文应提供更多上下文Spark SQL queries on partitioned data using Date Ranges。但是显然,这更加手动和复杂。

更新:更多示例Can I read multiple files into a Spark Dataframe from S3, passing over nonexistent ones?

也来自“ Spark-权威指南:简化大数据处理” 比尔·钱伯斯(Bill Chambers):

  

分区是一种工具,可让您控制存储哪些数据   (以及写在哪里)。当您将文件写入分区时   目录(或表)中,您基本上将一列编码为文件夹。什么   这允许您做的就是在读入数据时跳过大量数据   以后,仅允许您读入与问题相关的数据   不必扫描整个数据集。   ...

     

这可能是在以下情况下可以使用的最低要求的优化   您有一个读者经常过滤的表格   操纵。例如,日期对于   分区,因为在下游,我们通常只希望查看   前一周的数据(而不是扫描整个记录列表)。