Apache spark 查找给定单个门店位置的最近门店+;pyspark中的最大广播变量大小是多少?

Apache spark 查找给定单个门店位置的最近门店+;pyspark中的最大广播变量大小是多少?,apache-spark,pyspark,pyspark-sql,Apache Spark,Pyspark,Pyspark Sql,我正在尝试读取一个文件,其中包含所有杂货店的RDD。目标是为给定的杂货店找出最近的500家商店,并进行一些处理。 例如,如果一家商店被占领,我必须找到该城市的所有商店。如果我在RDD上进行映射,我将获得转换函数的单个存储。我如何获得该功能中的所有存储 片段 def getNearestStores(store): stores_city = stores.filter("city="+store.city) return (store.id,stores_city.count()

我正在尝试读取一个文件,其中包含所有杂货店的RDD。目标是为给定的杂货店找出最近的500家商店,并进行一些处理。 例如,如果一家商店被占领,我必须找到该城市的所有商店。如果我在RDD上进行映射,我将获得转换函数的单个存储。我如何获得该功能中的所有存储

片段

def getNearestStores(store):
    stores_city = stores.filter("city="+store.city)
    return (store.id,stores_city.count()) 
stores = sc.textFile("stores.json").map(getNearestStores).count()
这是简单的代码片段。Stores.json是一个巨大的文件

1) 我如何在getNearestStores函数中使用stores.json获得最近的500个存储


2) PySpark中的最大广播变量大小是多少?

~2GB是广播变量的最大大小,因为任何广播变量在序列化过程中变为java字节数组,并且java数组具有max size Integer.max_值

这些是与PySpark 2.x相关的较老(类似)的问题

跟踪此问题的JIRA:

编辑: 使用SparkSession+DataFrame(因为这是PySpark-2.x)按如下方式进行连接

from pyspark.sql import SparkSession

spark = SparkSession \
    .builder \
    .appName("Python Spark SQL basic example") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()
df = spark.read.json("stores.json")
nearest_stores_df = df.join(df, "city") # self-join

对你的评论做出回应,详细说明你真正想要实现的目标

我在spark中不使用python,但在scala中,我会这样开始。大多数重要的东西都是特定于spark的,应该很容易转换为python

商店类别:

class Store(val id: String, 
            val city: String, 
            val lat: Double, 
            val lon: Double) extends Haversine {

  // distance in km 
  def distance(that: Store) = {
    val radius = 6371 // earth in km 
    val dlat = toRadians(that.lat - this.lat)
    val dlon = toRadians(that.lon - this.lon)
    val a = sin(dlat/2) * sin(dlat/2) +
            cos(toRadians(this.lat)) * cos(toRadians(that.lat)) * sin(dlon/2) * sin(dlon/2)
    val c = 2 * atan2(sqrt(a), sqrt(1-a))
    val d = radius * c 
    d 
  }
}
既然您使用的是python,我将把JSON解析到类中留给您

// read JSON into class Store
val rdd_store: RDD[Store] = ???
这是最重要的部分。。。我的会像这样直到我把它调试好。。。但是如果我真的要使用它的话,我会把难以理解的部分转移到助手函数或类中

// result
val rdd2: RDD[(Store, List[Store])] = {
  rdd_store
  .keyBy(_.city)                               // RDD[(city, store)]               (one row per store)
  .groupByKey                                  // RDD[(city, all stores in city)]  (one row per city)
  .flatMap { case (city, iter_stores) =>
    iter_stores.map(one_store => {
      // up-to 500 closest stores in same city as 'one_store'
      val top500: List[Store] = {
        iter_stores
        .toList
        .map { s => 
          val dist = one_store distance s
          (dist, s)
        }
      }.sorted.take(500).map{ case (dist, that_store) => that_store }

      // result
      (one_store, top500)
    })
  }                                           // RDD[(store, list of top 500 stores in same city)] (one row per store)
}

好啊这是有道理的。但是你知道我该如何解决上述问题吗?是的。1) 使用SparkSession+DataFrame或Dataset,2)为门店创建一个表,并在city上进行连接,而不是广播的高成本如果我从代码中理解了这项任务,那就是为每个门店获取同一城市中所有门店的计数。。。如果这是对的,我不会使用广播变量。。。我会在RDD[商店]上执行类似的操作,以获得RDD[(商店id,计算同一城市的商店)]
rdd.keyBy(u.city).groupByKey.flatMap{case(city,iter_stores)=>iter_stores.map(one_store=>(one_store.id,iter_stores.size))}
@kmh这不仅仅是计数。还需要执行其他处理。这里是一个完整的用例:对于每个商店,在同一个城市中找到附近的500家商店,并对这500家商店进行一些处理。最终的结果是(商店,[500家附近的加工商店]),我仍然会做一个keyBy,groupByKey,flatMap来到达那里。我还想更改您问题的标题,因为这实际上与广播变量max size.Ok无关。这真的很有帮助。非常感谢你。请给我另一个建议:如果这个城市没有500家店铺,我有另一个文件,上面写着去500家店铺要选哪个城市。我怎么能那样做呢。