【问题标题】:Alternative to using cross-join when dealing with two tables with millions of rows处理具有数百万行的两个表时使用交叉连接的替代方法
【发布时间】:2022-01-21 09:33:36
【问题描述】:

我正在按照下面的脚本在 BigQuery 上查找最近的经纬度记录。

#standardSQL
SELECT AS VALUE ARRAY_AGG(STRUCT<id_a INT64, id_b STRING>(a.id, b.id) ORDER BY 
ST_DISTANCE(a.point, b.point) LIMIT 1)[OFFSET(0)] 
FROM (SELECT id, ST_GEOGPOINT(lon, lat) point FROM `project.dataset.table_a`) a
CROSS JOIN (SELECT id, ST_GEOGPOINT(lon, lat) point FROM `project.dataset.table_b`) b 
GROUP BY a.id

来源 SQL: Finding the closest Lat/Lon record on Google BigQuery

但是,我的查询不会完成,我将在 BQ 中达到 6 小时标记。这可能是由于我正在使用的表的大小。

table_a has 27M rows
table_b has 120M rows

您对我如何修改上面的脚本以使其适用于我的表格大小有什么建议吗?

欣赏任何见解。谢谢。

【问题讨论】:

    标签: google-bigquery


    【解决方案1】:

    试试下面的替代方案

    SELECT a_id, b_id FROM (
      SELECT a.id a_id, b.id b_id, ST_DISTANCE(a.point, b.point) distance
      FROM (SELECT id, ST_GEOGPOINT(lon, lat) point FROM `project.dataset.table_a`) a
      CROSS JOIN (SELECT id, ST_GEOGPOINT(lon, lat) point FROM `project.dataset.table_b`) b 
    )
    WHERE true
    QUALIFY 1 = ROW_NUMBER() OVER(PARTITION BY a_id ORDER BY distance)
    

    【讨论】:

    • 这给了我“查询执行期间资源超出”错误。
    【解决方案2】:

    另一种选择

    SELECT a_id, APPROX_TOP_SUM(b_id, 1 / distance, 1)[OFFSET(0)].value as b_id
    FROM (
      SELECT a.id a_id, b.id b_id, ST_DISTANCE(a.point, b.point) distance
      FROM (SELECT id, ST_GEOGPOINT(lon, lat) point FROM `project.dataset.table_a`) a
      CROSS JOIN (SELECT id, ST_GEOGPOINT(lon, lat) point FROM `project.dataset.table_b`) b 
    )
    GROUP BY a_id         
    

    这种方法使用APPROX_TOP_SUM
    注意:近似聚合函数在内存使用和时间方面是可伸缩的,但会产生近似结果而不是精确结果。

    【讨论】:

    • 谢谢,我试试这个。
    • 我试过了,但我没有达到 6 小时标记,但是 BigQuery 给了我“查询超出资源限制”。我在表 b 中的数据有 12 个不同的状态,所以我可以将 120M 行拆分为每行大约 10M 行并运行查询 12 次,最后合并。还有比这更有效的方法吗?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 2017-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 1970-01-01
    相关资源
    最近更新 更多