spark04-文件读取分区数据分配原理

文章介绍了Spark通过SparkConf和SparkContext读取文本文件的方式,强调了它以Hadoop的方式按行读取数据,不考虑字节数。每行数据的偏移量不会被重读,且数据分区基于偏移量范围,例如0号分区读取了1&&2,1号分区读取了3。因此,分区文件中的内容反映了这种读取模式。

https://blog.youkuaiyun.com/oracle8090/article/details/129013345?spm=1001.2014.3001.5502

通过上一节知道 总字节数为7 每个分区字节数为3

代码

  val conf: SparkConf = new SparkConf().setMaster("local").setAppName("wordcount")
 
    val sc: SparkContext = new SparkContext(conf)
    val rdd: RDD[String] = sc.textFile("datas/1.txt",2)
    rdd.saveAsTextFile("output")

通过运营最终得到的输出文件为:

part-00002为空文件

1.spark读取文件采用的是Hadoop方式读取,所以一行一行读取,跟字节数没有关系

2.数据读取时以偏移量为单位,偏移量不会被重新读取

/*数据(回车占两字符)=》偏移量

1@@ =>0 1 2

2@@ =>3 4 5

3 =>6

*/

3 数据分区的偏移量范围

0号分区 =>[0,3]=>1 2 偏移量是0-3 读取1@@ 2,但是以行为单位读取最终读取的为1@@,2@@,因此第一个分区文件分配的数字为1 2

1号分区 =>[3,6] => 3 偏移量是3-6 但是3 4 5 偏移量已经被0号分区读取过了,因此第二个分区文件分配的数字为3

2号分区 =>[6,7]

### 使用 `spark.read.parquet` 方法读取指定日期范围的 Parquet 文件分区 要通过 Spark SQL 的 `spark.read.parquet` 方法读取特定日期范围内的 Parquet 文件分区,可以通过以下方式实现: #### 1. 构建路径列表 如果 Parquet 数据是以 Hive 表的形式存储在 HDFS 上,并且具有按日期划分的分区结构,则可以直接构建这些分区对应的路径并传递给 `spark.read.parquet()` 方法。假设分区字段名为 `dt`,其格式为 `yyyyMMdd`。 以下是代码示例: ```python from pyspark.sql import SparkSession # 初始化 SparkSession spark = SparkSession.builder.appName("ReadParquetByDateRange").getOrCreate() # 定义起始和结束日期 start_date = "20250124" end_date = "20250323" # 基础路径 (Hive 表所在的 HDFS 路径) base_path = "/path/to/hive/table/dt=" # 创建日期范围内的路径列表 date_range_paths = [ f"{base_path}{date}" for date in pd.date_range(start=start_date, end=end_date).strftime("%Y%m%d") ] # 使用 spark.read.parquet 加载多个路径 df = spark.read.parquet(*date_range_paths) # 显示 DataFrame 内容 df.show() ``` 上述代码中,`pd.date_range` 是 Pandas 库中的函数,用于生成指定范围内的一系列日期[^5]。每条路径都对应于一个具体的分区文件夹。 --- #### 2. 过滤分区列 另一种更高效的方式是利用 Spark 自带的分区过滤功能。这种方法不需要手动列举所有可能的路径,而是让 Spark 根据分区列自动筛选符合条件的数据。 以下是代码示例: ```python # 如果数据已经注册为 Hive 表或者视图 table_name = "your_hive_table" # 查询指定日期范围的数据 query = """ SELECT * FROM {table} WHERE dt >= '{start}' AND dt <= '{end}' """.format(table=table_name, start=start_date, end=end_date) # 执行查询并将结果加载到 DataFrame 中 df = spark.sql(query) # 或者直接使用 filter API 对已有的 DataFrame 进行操作 df_filtered = ( spark.table(table_name) .filter(f"dt BETWEEN '{start_date}' AND '{end_date}'") ) # 展示结果 df.show() ``` 此方法依赖于 Spark SQL 的分区裁剪能力,在底层会跳过不符合条件的分区文件[^2]。 --- #### 3. 参数调优 为了提高性能,建议调整以下几个参数以优化 Parquet 文件读取效率: - **`spark.sql.files.maxPartitionBytes`**: 控制单个 partition 的最大字节数,默认值为 128 MB。 - **`spark.sql.files.openCostInBytes`**: 设置打开新文件的成本,默认值为 4 MB。 例如: ```python spark.conf.set("spark.sql.files.maxPartitionBytes", "67108864") # 设为 64MB spark.conf.set("spark.sql.files.openCostInBytes", "16777216") # 设为 16MB ``` 以上配置有助于减少小文件的影响以及提升 shuffle 性能。 --- ### 注意事项 - 当从 Hive Metastore 中读取 Parquet 表时,需确认是否启用了 `spark.sql.hive.convertMetastoreParquet=true` 配置项。该选项允许 Spark 使用自身的高性能 Parquet 解析器替代 Hive 默认解码器[^3]。 - 若遇到权限不足或其他异常情况,请检查日志输出 (`logInfo`) 并验证是否有足够的资源分配给作业运行。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值