查询超出Bigquery中的资源限制

时间:2018-08-22 07:32:50

标签: sql google-bigquery

为了找到特定IP地址的国家/地区,我使用的是Maxmind IP地址数据库。我已经下载了数据库并将其导入到Google BigQuery中,因此可以对其进行查询。在一个单独的表中,我从系统中的某些事件捕获IP地址。我现在想加入这两个数据源。

Maxmind数据库中的列如下:

  • start_ip_range STRING可空
  • end_ip_range STRING可空
  • start_ip_num STRING为空
  • end_ip_num STRING为空
  • 国家/地区代码STRING为空
  • 国家名

我的事件表中的列是:

  • request_id STRING为空
  • ip_address STRING NULLABLE

如此处(https://dev.maxmind.com/geoip/legacy/csv/所述,有一种方法可以获取IP地址的整数表示形式,因此我可以使用它来查询IP地址并检索country_code或country_name。

我现在构造了以下查询:

SELECT
  p.*,
  g.country_code AS country_code
FROM
  `dev.event_v1` p
INNER JOIN
  `dev.geo_ip_countries` g
ON
  SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(0)] AS NUMERIC)*16777216 + 
  SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(1)] AS NUMERIC)*65536 + 
  SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(2)] AS NUMERIC)*256 + 
  SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(3)] AS NUMERIC)
BETWEEN 
  SAFE_CAST(g.start_ip_num AS INT64)
AND 
  SAFE_CAST(g.end_ip_num AS INT64)
LIMIT 100

但是,这在使用限制时有效,它不适用于构造视图。

两个问题: 1.有没有一种方法可以简化查询 2.当我尝试返回较大的结果集时,Google BigQuery引发错误:

Error: Query exceeded resource limits. 28099.974050246612 CPU seconds were used, and this query must use less than 5600.0 CPU seconds.

感谢您的帮助!

解决方案 将查询重写为以下内容可以解决资源限制问题:

SELECT
  p.*,
  g.country_code
FROM
  `dev.event_v1` p
INNER JOIN
  `dev.geo_ip_countries` g
ON 
  NET.IP_TRUNC(NET.SAFE_IP_FROM_STRING(p.ip_address),16) = NET.IP_TRUNC(NET.SAFE_IP_FROM_STRING(g.start_ip_range),16)
WHERE 
  NET.SAFE_IP_FROM_STRING(p.ip_address) 
  BETWEEN 
    NET.SAFE_IP_FROM_STRING(g.start_ip_range) 
  AND 
    NET.SAFE_IP_FROM_STRING(g.end_ip_range)

1 个答案:

答案 0 :(得分:2)

Try below (BigQuery Standard SQL)

#standardSQL
SELECT
  p.* EXCEPT(ip_address_num),
  g.country_code AS country_code
FROM (
  SELECT *, 
    SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(0)] AS NUMERIC)*16777216 + 
    SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(1)] AS NUMERIC)*65536 + 
    SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(2)] AS NUMERIC)*256 + 
    SAFE_CAST(SPLIT(p.ip_address, ".")[OFFSET(3)] AS NUMERIC) ip_address_num
  FROM `dev.event_v1` 
) p
INNER JOIN (
  SELECT 
    SAFE_CAST(g.start_ip_num AS INT64) start_ip_num, 
    SAFE_CAST(g.end_ip_num AS INT64) end_ip_num,
    country_code
  FROM `dev.geo_ip_countries`
) g
ON ip_address_num BETWEEN g.start_ip_num AND g.end_ip_num