作为参数传递时,pyspark 数据帧是作为引用还是值传递?
is pyspark dataframe when passed as argument, passed as reference or value?
假设我有这个代码:
def func1():
# some code to create a dataframe df
df.persist(StorageLevel.MEMORY_AND_DISK)
return df.repartition("col1", "col2")
def func2(df: Dataframe):
df = (df.select("col1", "col2").groupby("col1").count().withColumnRenamed("count", "count_col1"))
return df
所以在 func2 中,当我传递变量 'df' 时,它是通过引用传递还是通过值传递?我在 func1 中应用的 repartition(),在将 func2 中的 df 用于 groupBy 时应该有助于提高性能?
同样,如果我在 func1 中应用 persist(),那么它将正确保存在内存中,然后当我在 func2() 中引用 df 时,它将从在 func1() 中仅保存一次的同一位置引用.对吗?
谢谢!
在Python中,如果我们想了解参数何时作为值或引用传递,我们需要了解该参数是可变的还是不可变的。
- 可变对象是指在初始化后可以更改其值的对象(如列表、字典、集合)。它们是通过引用调用的。
- 不可变对象是指在初始化后其值无法更改的对象(如 int、string、tuple、class 对象)。为了改变它们的值,我们需要重新初始化它们。它们按值调用。
PySpark Dataframes 属于 class 对象类别并且是不可变的,因此按值调用。
这里有两个方面:
- Pyton 变量
df
是作为值传递还是作为引用传递?
df
引用的数据是如何传递的?
对于第一个问题,有一些可用的答案,例如 this one。但这是一个关于 Python 的问题,如果我们想知道 Spark 如何处理数据帧中的数据,它并不真正相关。
要回答第二个问题,我们应该考虑 df
到底是什么。 df
不包含实际数据,甚至不是对其的直接引用。取而代之的是所有 Spark transformations are recorded within the execution plan of this object and when finally an action like save
, count
or collect
is called, Spark executes (after some optimizations) 这个计划。这是 Spark 的执行程序第一次实际移动任何数据。
要检查执行计划,您可以调用 DataFrame.explain。如果你 运行 这个函数你会注意到 - 无论你的 Spark 逻辑多么复杂 - 它都会立即 returns 并打印出执行计划。这种快速响应的原因是没有执行实际的数据操作 - 直到您 运行 一个 Spark 操作。
TL;DR:传递一个 Python 变量永远不会移动数据帧的任何数据。你最后一个问题的答案是是。
假设我有这个代码:
def func1():
# some code to create a dataframe df
df.persist(StorageLevel.MEMORY_AND_DISK)
return df.repartition("col1", "col2")
def func2(df: Dataframe):
df = (df.select("col1", "col2").groupby("col1").count().withColumnRenamed("count", "count_col1"))
return df
所以在 func2 中,当我传递变量 'df' 时,它是通过引用传递还是通过值传递?我在 func1 中应用的 repartition(),在将 func2 中的 df 用于 groupBy 时应该有助于提高性能? 同样,如果我在 func1 中应用 persist(),那么它将正确保存在内存中,然后当我在 func2() 中引用 df 时,它将从在 func1() 中仅保存一次的同一位置引用.对吗?
谢谢!
在Python中,如果我们想了解参数何时作为值或引用传递,我们需要了解该参数是可变的还是不可变的。
- 可变对象是指在初始化后可以更改其值的对象(如列表、字典、集合)。它们是通过引用调用的。
- 不可变对象是指在初始化后其值无法更改的对象(如 int、string、tuple、class 对象)。为了改变它们的值,我们需要重新初始化它们。它们按值调用。
PySpark Dataframes 属于 class 对象类别并且是不可变的,因此按值调用。
这里有两个方面:
- Pyton 变量
df
是作为值传递还是作为引用传递? df
引用的数据是如何传递的?
对于第一个问题,有一些可用的答案,例如 this one。但这是一个关于 Python 的问题,如果我们想知道 Spark 如何处理数据帧中的数据,它并不真正相关。
要回答第二个问题,我们应该考虑 df
到底是什么。 df
不包含实际数据,甚至不是对其的直接引用。取而代之的是所有 Spark transformations are recorded within the execution plan of this object and when finally an action like save
, count
or collect
is called, Spark executes (after some optimizations) 这个计划。这是 Spark 的执行程序第一次实际移动任何数据。
要检查执行计划,您可以调用 DataFrame.explain。如果你 运行 这个函数你会注意到 - 无论你的 Spark 逻辑多么复杂 - 它都会立即 returns 并打印出执行计划。这种快速响应的原因是没有执行实际的数据操作 - 直到您 运行 一个 Spark 操作。
TL;DR:传递一个 Python 变量永远不会移动数据帧的任何数据。你最后一个问题的答案是是。