2017-10-06 5 views
0

J'ai une liste de comptes et d'adresses IP et j'essaie d'obtenir un résumé des emplacements. Cependant, les calculs sont trop lourds pour nos serveurs et je me demande s'il y a un moyen de modifier mon code, je peux obtenir tous mes résultats. L'ensemble de données du compte est d'environ 150k lignes et 2 colonnes.Conversion d'adresses IP en emplacements, besoin d'optimisations

select city, state, count(*) from(
    select account_id, 256*256*256*one+256*256*two+256*three+four as Converted, city, state from 
     (select *, convert(bigint, split_part(ip_address, '.', 1)) as one, convert(int, split_part(ip_address, '.', 2)) as two, 
     convert(int, split_part(ip_address, '.', 3)) as three, convert(int, split_part(ip_address, '.', 4)) as four from AccountsIP) 
    inner join 
    (select city, state, ip_from, ip_to from ip_ranges a left join ip_locations b on a.ip_location_id = b.ip_location_id 
     where country = 'US') b 
     on (256*256*256*one+256*256*two+256*three+four) between ip_from and ip_to 
) 
group by city, state 

Répondre

0

Vous pouvez créer un Python UDF pour convertir l'adresse IP à bigint et l'utiliser dans BETWEEN état:

create or replace function ip_to_ipnum (ip varchar) 
    returns bigint 
    stable as $$ 
    ip_array = ip.split('.') 
    return int(ip_array[0])*16777216+int(ip_array[1])*65536+int(ip_array[2])*256+int(ip_array[3]) 
$$ language plpythonu; 

En outre, le goulot d'étranglement peut-être dans vos ip_ranges et ip_locations tables qui doivent être triés de manière appropriée. Si vos données sont uniquement aux États-Unis, vous pouvez supprimer toutes les autres données au lieu de filtrer et trier la table par (ip_from, ip_to) afin que les recherches soient plus efficaces.

De plus, comme les données dans ip_ranges et ip_locations ne sont pas très volatiles, vous pouvez créer une table physique avec la jointure de celles-ci afin de ne pas avoir à les joindre à chaque fois dans la requête ci-dessus.