我有一个巨大的地理定位事件列表:
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.htmlStackO:如何提高BigQuery中GeoIP查询的性能?