使用lat / long标记巨大的元素列表,其中包含大量的地理位置数据

时间:2015-10-22 13:33:49

标签: redis apache-spark geolocation google-bigquery google-cloud-dataflow

我有很多地理定位事件:

Event (1 billion)
------
id
datetime
lat
long

从开放街道地图加载的兴趣点列表:

POI (1 million)
------
id
tag   (shop, restaurant, etc.)
lat
long

我想为每个事件分配兴趣点的标记。实现此问题的最佳架构是什么?我们尝试使用Google BigQuery,但我们必须进行交叉连接,但它不起作用。我们愿意使用任何其他大数据系统。

2 个答案:

答案 0 :(得分:3)

使用Dataflow,您可以使用CoGroupByKey轻松地进行交叉连接。使用此方法,只有您要加入的事件和POI需要适合内存(如果给定键的项目列表太大而无法容纳在内存中,Dataflow将自动溢出到磁盘)。

这里有更多细节。

  • 创建由纬度和经度键入的事件的PCollection。
  • 创建由纬度和经度键入的POI的PCollection
  • 使用CoGroupByKey加入两个PCollections。
  • 编写一个处理CoGbkResult
  • 的DoFn
  • DoFn看起来像:

    
    PCollection<T> finalResultCollection =
    coGbkResultCollection.apply(ParDo.of(
      new DoFn<KV<K, CoGbkResult>, T>() {
        @Override
        public void processElement(ProcessContext c) {
          KV<K, CoGbkResult> e = c.element();
          // Get all collection 1 values
          Iterable<Event> eventVals = e.getValue().getAll(eventTag);
          // Now get collection 2 values
          Iterable<Poi> poiVals = e.getValue().getAll(poiTag);
          for (Event e : eventVals) {
            for (Poi p : poiVal) {
              ...
              c.output(...tagged event...);
            }
          }
        }
      }));
    

如此Answer中所述,您还可以使用侧输入来传递其键是纬度和经度的地图,值是POI的详细信息。如果数据可以适合内存,那么该方法将起作用。如果您只有100万个POI并且您只存储列出的字段,那么它可能会适合内存。

注意:我在Dataflow团队。

答案 1 :(得分:1)

您可以打开包含开放街道地图表的数据集吗? (毕竟这是开放的数据)。使用该表,我可以尝试优化查询。

对于类似的问题,我通过为每一行生成键来优化它,可以用来避免对整个数据集进行CROSS JOIN。

http://googlecloudplatform.blogspot.com/2014/03/geoip-geolocation-with-google-bigquery.html

StackO:How to improve performance of GeoIP query in BigQuery?