用大列表的地理位置数据标记巨大的元素列表



我有一个巨大的地理定位事件列表:

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

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

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

我想给每个事件分配兴趣点的标签。实现这个问题的最佳体系结构是什么?我们尝试使用Google BigQuery,但我们必须做一个交叉连接,它不起作用。我们对使用其他大数据系统持开放态度。

使用Dataflow,您可以很容易地使用CoGroupByKey进行交叉连接。使用这种方法,只有您要加入的Event和POI需要装入内存(如果给定键的项列表太大而无法装入内存,则数据流将自动溢出到磁盘)。

这里有更多的细节

  • 创建一个由纬度和经度键控的事件PCollection。
  • 创建一个POI的PCollection,由经度和纬度键化
  • 使用CoGroupByKey连接两个PCollections
  • 写一个DoFn处理CoGbkResult
  • 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团队的成员。

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

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

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

StackO:如何提高BigQuery中GeoIP查询的性能?

最新更新