我想知道下面的伪代码是否是从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");
答案 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):
分区是一种工具,可让您控制存储哪些数据 (以及写在哪里)。当您将文件写入分区时 目录(或表)中,您基本上将一列编码为文件夹。什么 这允许您做的就是在读入数据时跳过大量数据 以后,仅允许您读入与问题相关的数据 不必扫描整个数据集。 ...
这可能是在以下情况下可以使用的最低要求的优化 您有一个读者经常过滤的表格 操纵。例如,日期对于 分区,因为在下游,我们通常只希望查看 前一周的数据(而不是扫描整个记录列表)。