PySpark 之 Spark RDD的创建

一、并行化创建RDD

from pyspark import SparkContext,SparkConf
import os

os.environ['SPARK_HOME'] = '/exportrver/spark'
PYSPARK_PYTHON = "/root/anaconda3/envs/pyspark_env/bin/python"
os.environ['PYSPARK_PYTHON'] = PYSPARK_PYTHON
os.environ['PYSPARK_DRIVER_PYTHON'] = PYSPARK_PYTHON

if __name__ == '__main__':
    print("PySpark First Program")
    # 输入数据
    data = ["hello","world","hello","world"]
    conf = SparkConf().setAppName("miniProject").setMaster("local[*]")
    sc = SparkContext(conf=conf)
    # 将collection的data转为spark中的rdd并进行操作
    rdd = sc.parallelize(data)
    # 执行map转化操作以及reduceByKey的聚合操作
    res_rdd = rdd.map(lambda word:(word,1)).reduceByKey(lambda a,b:a+b)
    # 将rdd转为collection并打印
    res_rdd_coll = res_rdd.collect()
    for line in res_rdd_coll:
        print(line)
    print('停止PySpark SparkSession对象')
    sc.stop()

二、小文件读取

在实际项目中,有时往往处理的数据文件属于小文件,文件数量又很大,如果一个个文件读取为一个个分区,计算数据时很耗时性能很低,使用SparkContext中提供的wholeTextFiles类,专门读取小文件数据

from pyspark import SparkContext, SparkConf
import os

os.environ['SPARK_HOME'] = '/export/server/spark'
PYSPARK_PYTHON = '/root/anaconda3/envs/pyspark_env/bin/python'
os.environ['PYSPARK_PYTHON'] = PYSPARK_PYTHON
os.environ['PYSPARK_DRIVER_PYTHON'] = PYSPARK_PYTHON

if __name__ == '__main__':
    print("PySpark WholeTextFile Program")
    # 1.创建应用程序入口SparkContext实例对象
    conf = SparkConf().setAppName("miniProject").setMaster("local[*]")
    sc = SparkContext.getOrCreate(conf)
    # 2.从文件系统加载数据,调用textFile
    resultRDD1 = sc.textFile("file:///export/server/spark/conf")
    # 3.调用集合RDD中函数处理分析数据,调用wholeTextFiles
    resultRDD2 = sc.wholeTextFiles("file:///export/server/spark/conf")
    # 4.获取分区数
    print(f"textFile numpartitions:{resultRDD1.getNumPartitions()}")
    print(f"whole textFile numpartitions:{resultRDD2.getNumPartitions()}")
    print("停止PySpark SparkSession对象")
    sc.stop()

三、通过外部数据创建RDD

  • PySpark可以从Hadoop支持的任何存储源创建RDD,包括本地文件系统,HDFS,Cassandra,Hbase,Amazon S3等
  • 支持整个目录、多文件、通配符
  • 支持压缩文件
from pyspark import SparkContext, SparkConf
import os
import re
os.environ['SPARK_HOME'] = '/export/server/spark'
PYSPARK_PYTHON = '/root/anaconda3/envs/pyspark_env/bin/python'
os.environ['PYSPARK_PYTHON'] = PYSPARK_PYTHON
os.environ['PYSPARK_DRIVER_PYTHON'] = PYSPARK_PYTHON

if __name__ == '__main__':
    print("PySpark RDD Program")
    # 1.创建应用程序入口SparkContext实例对象
    conf = SparkConf().setAppName("miniProject").setMaster("local[*]")
    sc = SparkContext.getOrCreate(conf)
    # 2.从文件系统加载数据,创建RDD数据集
    # 3.调用集合RDD中函数处理分析数据
    resultRDD = sc.textFile("file:///export/tmp_data/word.txt")\
        .flatMap(lambda line:re.split("\s+",line))\
        .map(lambda x: (x,1))\
        .reduceByKey(lambda a,b:a+b)
    # 4.保存结果RDD到外部存储系统(HDFS、MySQL、HBase...)
    res_rdd_coll = resultRDD.collect()
    for line in res_rdd_coll:
        print(line)
    print("停止PySpark SparkSession对象")
    # 关闭SparkContext
    sc.stop()

四、RDD分区数

分区是一个偏物理层的概念,也是RDD并行计算的单位

  • 数据在RDD内部被切分为多个子集合,每个子集合可以被认为是一个分区,运算逻辑最小会被应用在每一个分区上,每个分区是由一个单独的任务(task)来执行的,所以分区数越多,整个应用的并行度也会越高
  • 获取RDD分区数目方式:pyspark.RDD.getNumPartitions

五、RDD分区数据的决定因素

  1. RDD分区的原则是使得分区的个数尽量等于集群中CPU核心(core)数目,这样可以充分利用CPU的计算资源
  2. 在实际中为了更加充分的压榨CPU的计算资源,会把并行度设置为cpu核数的2~3倍
  3. RDD分区数和启动时指定的核数、调用方法时指定的分区数、如文件本身分区数有关系
    1. 启动的时候指定的CPU核数确定了一个参数值
      1. Spark.default.parallelism=指定的CPU核数(集群模式最小2)
    2. 对于Scala集合调用parallelize(集合,分区数)方法
      1. 如果没有指定分区数,就使用spark.default.parallelism
      2. 如果指定了就使用指定的分区数(建议不要指定大于spark.default.parallelism)
    3. 但对于textFile(文件、分区数)
      1. defaultMinPartitions
      2. 如果没有指定分区数sc.defaultMinPartitions=min(defaultParallelism,2)
      3. 如果指定了就使用指定的分区数sc.defaultMinPartitions=指定的分区数rdd的分区数
    4. rdd的分区数
      1. 对于本地文件
        1. rdd的分区数 = max(本地file的分片数,sc.defaultMinPartitions)
      2. 对于HDFS文件
        1. rdd的分区数 = max(hdfs文件的block数目,sc.defaultMinPartitions)
        2. 如果分配的核数为多个,且从文件中读取数据创建RDD,即使hdfs文件只有一个切片,最后的Spark的RDD的partition数也有可能是2

你可能感兴趣的:(#,Spark计算引擎,spark,big,data,python)