找到最近的商店给定单店位置+什么是pyspark中的最大广播变量大小?

时间:2018-02-08 00:57:04

标签: apache-spark pyspark pyspark-sql

我试图将所有杂货店的文件读入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中的最大广播变量大小是多少?

2 个答案:

答案 0 :(得分:2)

~2GB是广播变量的最大大小,因为任何广播变量在序列化期间变为java字节数组且java数组的最大大小为Integer.MAX_VALUE。

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

Is there any limit on size of a spark broadcast variable?

Evaluate the max size for a spark broadcast variable

用于跟踪此问题的JIRA:https://issues.apache.org/jira/browse/SPARK-6235

编辑: 使用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

答案 1 :(得分:0)

回复上面的评论,详细说明您真正要完成的工作。

我不在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)
}