Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Spark知道数据帧的分区键吗?_Apache Spark_Partitioning_Window Functions - Fatal编程技术网

Apache spark Spark知道数据帧的分区键吗?

Apache spark Spark知道数据帧的分区键吗?,apache-spark,partitioning,window-functions,Apache Spark,Partitioning,Window Functions,我想知道Spark是否知道拼花地板文件的分区键,并使用此信息来避免混乱 上下文: 运行Spark 2.0.1运行本地SparkSession。我在磁盘上保存了一个csv数据集作为拼花文件,如下所示: val df0 = spark .read .format("csv") .option("header", true) .option("delimiter", ";") .option("inferSchema", false) .load("SomeFile.csv")

我想知道Spark是否知道拼花地板文件的分区键,并使用此信息来避免混乱

上下文:

运行Spark 2.0.1运行本地SparkSession。我在磁盘上保存了一个csv数据集作为拼花文件,如下所示:

val df0 = spark
  .read
  .format("csv")
  .option("header", true)
  .option("delimiter", ";")
  .option("inferSchema", false)
  .load("SomeFile.csv"))


val df = df0.repartition(partitionExprs = col("numerocarte"), numPartitions = 42)

df.write
  .mode(SaveMode.Overwrite)
  .format("parquet")
  .option("inferSchema", false)
  .save("SomeFile.parquet")
我正在按列
numerocate
创建42个分区。这应该将多个
numerocarte
分组到同一分区。我不想在
写入时执行partitionBy(“numerocate”),因为我不希望每张卡都有一个分区。这将是数百万人

在另一个脚本中,我阅读了这个
SomeFile.parquet
parquet文件并对其进行了一些操作。特别是,我在上面运行了一个
窗口函数
,其中分区是在拼花地板文件被重新分区的同一列上完成的

import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._

val df2 = spark.read
  .format("parquet")
  .option("header", true)
  .option("inferSchema", false)
  .load("SomeFile.parquet")

val w = Window.partitionBy(col("numerocarte"))
.orderBy(col("SomeColumn"))

df2.withColumn("NewColumnName",
      sum(col("dollars").over(w))
读取后
我可以看到
重新分区
按预期工作,DataFrame
df2
有42个分区,每个分区中都有不同的卡

问题:

  • Spark是否知道数据帧
    df2
    由列
    Numerocate
    进行分区
  • 如果它知道,那么窗口函数中就不会有随机播放。是吗
  • 如果它不知道,它将在窗口函数中执行洗牌。是吗
  • 如果它不知道,我如何告诉Spark数据已经被右列分区
  • 如何检查
    DataFrame
    的分区键?有这个命令吗?我知道如何检查分区数,但如何查看分区键
  • 当我在每个步骤后打印文件中的分区数时,我在
    read
    之后有42个分区,在
    withColumn
    之后有200个分区,这表明Spark重新分区了我的
    DataFrame
  • 如果有两个不同的表使用同一列重新分区,那么连接会使用该信息吗
  • Spark知道数据帧df2是由列Numerocate分区的吗

    事实并非如此

    如果它不知道,我如何告诉Spark数据已经被右列分区

    你没有。仅仅因为您保存了已被洗牌的数据,并不意味着它将加载相同的拆分

    如何检查DataFrame的分区键

    加载数据后没有分区键,但可以检查
    分区器的
    queryExecution


    实际上:

    • 如果要支持有效的按键,请使用
      DataFrameWriter
      partitionBy
      方法
    • 如果希望对联接优化提供有限的支持,请将
      bucketBy
      与metastore和持久表结合使用

    有关详细示例,请参见。

    我正在回答自己的问题,以备将来参考

    以下是@user8371915的建议,bucketBy works

    我正在保存数据帧
    df

    df.write
      .bucketBy(250, "userid")
      .saveAsTable("myNewTable")
    
    然后,当我需要加载此表时:

    val df2 = spark.sql("SELECT * FROM myNewTable")
    
    val w = Window.partitionBy("userid")
    
    val df3 = df2.withColumn("newColumnName", sum(col("someColumn")).over(w)
    df3.explain
    
    我确认当我在
    df2
    上执行由
    userid
    分区的窗口功能时,不会出现无序移动!谢谢@user8371915

    我在调查过程中学到的一些东西

    • myNewTable看起来像一个普通的拼花锉刀,但事实并非如此。您可以使用
      spark.read.format(“parquet”).load(“path/to/myNewTable”)
      正常读取它,但是以这种方式创建的
      DataFrame
      将不会保留原始分区!必须使用
      spark.sql
      选择
      ,才能正确分区
      DataFrame
    • 您可以使用
      spark.sql(“descripe formatted myNewTable”).collect.foreach(println)
      查看表内部。这将告诉您使用了哪些列来制作木桶,以及有多少个木桶
    • 利用分区的窗口函数和联接通常也需要排序。您可以在写入时使用
      .sortBy()
      对存储桶中的数据进行排序,排序也将保留在配置单元表中
      df.write.bucketBy(250,“userid”).sortBy(“somColumnName”).saveAsTable(“myNewTable”)
    • 在本地模式下工作时,表
      myNewTable
      保存到本地Scala SBT项目中的
      spark warehouse
      文件夹中。通过
      spark submit
      以集群模式使用mesos进行保存时,会将其保存到hive warehouse。对我来说,它位于
      /user/hive/warehouse
    • 执行
      spark submit
      时,您需要向
      SparkSession
      添加两个选项:
      .config(“hive.metastore.uris”thrift://addres-to-your-master:9083”
      .enableHiveSupport()
      。否则,您创建的配置单元表将不可见
    • 如果要将表保存到特定的数据库,请在备份前执行
      spark.sql(“使用您的数据库”)
    2018年2月5日更新


    我在spark bucketing和创建蜂巢表时遇到了一些问题。请参阅

    中的问题、答复和评论,以检查您应该查看底层RDD的分区器数据框架<代码>df.rdd.partitioner
    。如果两个dfs具有相同的分区器,则可能不存在洗牌。您可以通过调用
    df来检查是否会出现混洗。解释
    。要检查分区数,请调用
    df.rdd.partitions.length
    。要更完整地解释分区,请参阅Spark Warehouse中的保存也将元数据保存在Metastore中,如分区、顺序等:),但这只是一个小问题addition@T.Gawęda但之前的操作没有元数据,是吗?请注意,OP使用
    重新分区
    。我必须检查,但是
    重新分区
    应该明确添加分区信息。然而,这是一个更为“常见”的补充,与问题关系不大;)准确地说。已向上投票:)来自