在 BigQuery 中优化查询
Optimize query in BigQuery
我正在尝试 运行 BigQuery 中的查询,但我收到“查询执行期间超出资源”。
其实我有两个tables :
Table user:
Id | User | Latitude | Longitude
1 | 1 | 50.83 | 4.01
2 | 1 | 50.84 | 4.03
3 | 2 | 48.78 | 2.87
4 | 3 | 47.42 | 8.53
…
Table point_of_interest:
Id | Latitude | Longitude | Range | Tag
1 | 50.81 | 3.98 | 0.05 | a;b;c;d
2 | 50.85 | 4.03 | 0.025 | a;c;e;f
3 | 40.80 | 3.87 | 0.04 | a;d;g
4 | 47.42 | 8.57 | 0.08 | b
…
目的是加入 table 以使用纬度、经度和范围标记所有用户。
为此,我使用了那个查询:
SELECT
u.User AS id,
GROUP_CONCAT(poi.Tag) AS tag
FROM (
SELECT
u.User,
poi.Tag,
FROM
[user] u
CROSS JOIN
[point_of_interest] poi
WHERE
u.Latitude BETWEEN poi.Latitude – poi.Range AND poi.Latitude + poi.Range
AND
u.Longitude BETWEEN poi.Longitude – poi.Range AND poi.Longitude + poi.Range )
GROUP BY
id
用户 table 当前为 520 MB,而 point_of_interest table 只有 565 KB,但可能会随着时间的推移而增长。
我想知道是否有更好的方法来实现这个目标,以及最好的架构。
编辑:
我也试过使用范围 LEFT JOIN EACH
但是 BigQuery 只支持 ON
关键字后的相等语句。
您需要拆分 table 和 运行 多个较小的查询。
像这样:
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 0
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 1
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 2
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 3
...
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 99
但是你需要找到一个像样的大数字而不是像我的例子中的 100,然后编写一段代码来为你自动执行此操作。首先手动尝试一个碎片,碎片中有相当多的记录。
您可以 WRITE_APPEND
将结果放入同一目的地 table 并与原始数据分开存储。
对于类似的问题,我通过为每一行生成键来优化它,可以用来避免必须对整个数据集进行 CROSS JOIN。
http://googlecloudplatform.blogspot.com/2014/03/geoip-geolocation-with-google-bigquery.html
StackO:How to improve performance of GeoIP query in BigQuery?
顺便说一句,这个问题与后面发布的问题 (Tag huge list of elements with lat/long with large list of geolocation data) 相关吗?
我正在尝试 运行 BigQuery 中的查询,但我收到“查询执行期间超出资源”。
其实我有两个tables :
Table user:
Id | User | Latitude | Longitude
1 | 1 | 50.83 | 4.01
2 | 1 | 50.84 | 4.03
3 | 2 | 48.78 | 2.87
4 | 3 | 47.42 | 8.53
…
Table point_of_interest:
Id | Latitude | Longitude | Range | Tag
1 | 50.81 | 3.98 | 0.05 | a;b;c;d
2 | 50.85 | 4.03 | 0.025 | a;c;e;f
3 | 40.80 | 3.87 | 0.04 | a;d;g
4 | 47.42 | 8.57 | 0.08 | b
…
目的是加入 table 以使用纬度、经度和范围标记所有用户。
为此,我使用了那个查询:
SELECT
u.User AS id,
GROUP_CONCAT(poi.Tag) AS tag
FROM (
SELECT
u.User,
poi.Tag,
FROM
[user] u
CROSS JOIN
[point_of_interest] poi
WHERE
u.Latitude BETWEEN poi.Latitude – poi.Range AND poi.Latitude + poi.Range
AND
u.Longitude BETWEEN poi.Longitude – poi.Range AND poi.Longitude + poi.Range )
GROUP BY
id
用户 table 当前为 520 MB,而 point_of_interest table 只有 565 KB,但可能会随着时间的推移而增长。
我想知道是否有更好的方法来实现这个目标,以及最好的架构。
编辑:
我也试过使用范围 LEFT JOIN EACH
但是 BigQuery 只支持 ON
关键字后的相等语句。
您需要拆分 table 和 运行 多个较小的查询。
像这样:
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 0
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 1
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 2
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 3
...
SELECT * FROM table WHERE ABS(HASH(id) % 100) == 99
但是你需要找到一个像样的大数字而不是像我的例子中的 100,然后编写一段代码来为你自动执行此操作。首先手动尝试一个碎片,碎片中有相当多的记录。
您可以 WRITE_APPEND
将结果放入同一目的地 table 并与原始数据分开存储。
对于类似的问题,我通过为每一行生成键来优化它,可以用来避免必须对整个数据集进行 CROSS JOIN。
http://googlecloudplatform.blogspot.com/2014/03/geoip-geolocation-with-google-bigquery.html
StackO:How to improve performance of GeoIP query in BigQuery?
顺便说一句,这个问题与后面发布的问题 (Tag huge list of elements with lat/long with large list of geolocation data) 相关吗?