2017-05-16 19 views
0

私は一緒に参加したいIPアドレスのテーブルとIPアドレス範囲のテーブル(start ip、end ip)を持っています。私は次のクエリでこの作業を行うことができました:BigQueryでIP範囲に効率的に参加する

SELECT * FROM `ips` i 
JOIN `ranges` a 
ON NET.SAFE_IP_FROM_STRING(i.ip) 
BETWEEN NET.SAFE_IP_FROM_STRING(a.start_ip) 
AND NET.SAFE_IP_FROM_STRING(a.end_ip) 

問題私がいる。それは本当にひどくスケールということです。 10個のIPに対してそれを行うには約8秒かかります.100は30秒かかり、1000は数分かかります。私は数千万の行のためにこれを行うことができるようにしたいと思います。 (私はNET.SAFE_IP_FROM_STRINGの出力を範囲テーブルに書き込もうとしましたが、約10%の速度しか上げず、スケーリングには役立ちません)。

範囲は重複しないので、入力テーブルのすべての行について、出力テーブルには0または1行が必要です。 LATERAL JOINはそれを可能にし、ほぼ確実に高速化しますが、BigQueryがそれらをサポートしているとは思いません。このクエリを高速かつスケーラブルにする方法は他にありますか?

答えて

2

フェリペの答えにリンクされているhttps://cloudplatform.googleblog.com/2014/03/geoip-geolocation-with-google-bigquery.htmlの記事を読んだところ、私は信じられないほど速く、本当にうまくスケールを合わせることができました。フェリペに言及されているように、トリックはプレフィックス(私は/ 16と一緒に行きました)に直接結合し、そのあとでフィルタリングすることです。私は/ 16より大きいものを複数のブロックに分割する範囲を前処理しています。

SELECT * FROM `ips` i 
JOIN `ranges` a 
ON a.prefix = NET.IP_TRUNC(NET.SAFE_IP_FROM_STRING(i.ip), 16) 
WHERE NET.SAFE_IP_FROM_STRING(i.ip) BETWEEN a.start_b AND a.end_b 

100万個の範囲に千万IPアドレスへの参加は、今もかから:

SELECT *, 
NET.SAFE_IP_FROM_STRING(start_ip) AS start_b, 
NET.SAFE_IP_FROM_STRING(end_ip) AS end_b, 
NET.IP_TRUNC(NET.SAFE_IP_FROM_STRING(start_ip), 16) as prefix 

参加クエリは、このようになります。私は、いくつかの追加のフィールドを追加し、このクエリでテーブルを上書き課金1段階で30秒!

1

私は#standardSQLのための私のクエリを更新する必要がありますが、基本的な秘密が小さく、JOINの領域を生成しているhttps://stackoverflow.com/a/20156581

上でこのような何かをしました。

サンプルデータセットを共有できる場合は、新しいクエリを提供していただきます。

関連する問題