对于大型数据集,加快 CIDR 范围内 IP 地址成员身份的检查速度

问题描述 投票:0回答:4

在 Postgres DB 中,我需要过滤表 A 中的数十万行,方法是仅包含行中 IP 地址列(inet 类型)与数千个 IP 地址块(输入 cidr) 在另一个表 B 中。我已经在第一个表中的 inet 地址和第二个表中的 cidr 范围上尝试了各种索引,但无论我做什么,规划器都会执行嵌套顺序扫描,应用 << operator to every pair of IP addresses and prefixes.

有没有办法通过索引或其他巧妙的技巧来加快速度? (我可以诉诸外部过程脚本,但我想知道它在 Postgres 中是否可行。)

谢谢!

sql postgresql indexing ip-address cidr
4个回答
12
投票

这是一个老问题,但在 Google 结果中很突出,所以在这里发布我的 2 美分:

使用 Postgres 9.4 及更高版本,您可以对 inet 和 cidr 使用 GIST 索引:https://www.postgresql.org/docs/current/gist.html

例如以下查询将使用 gist 索引(假设来自 MaxMind 免费数据集的表):

create index on geolite2_city_ipv4_block using gist (network inet_ops);

select * from geolite2_city_ipv4_block where network >>= '8.8.8.8';

2
投票

你看过ip4r吗? http://pgfoundry.org/projects/ip4r。 IIRC,INET 相关的查找真的很快。


2
投票

案件结案。为了让事情变得更快,请执行以下操作:

鉴于上述情况,如果您对所有比较地址使用 ip4 类型(假设您正在处理 v4 地址),那么规划器将利用这些列上的索引。

谢谢大家的帮助!


0
投票

已经部署了确保 CIDR 不重叠的规则,我只是使用了索引

btree tablename(network(addr))

给出

target
作为输入检查,如下所示:

SELECT target <<= addr FROM tablename WHERE network(addr) <= target ORDER BY network(addr) DESC LIMIT 1;

成功时返回 true,失败时返回 false 或不返回任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.