postgresql 对于大型数据集,加快CIDR范围内的IP地址成员资格检查

gk7wooem  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(4)|浏览(142)

在Postgres DB中,我需要过滤表A中的一组几十万行,只包括那些行中的IP地址列(类型为inet)与另一个表B中的几千个IP地址块(类型为cidr)中的任何一个相匹配的行。我已经在第一个表中的inet地址和第二个表中的cidr范围上尝试了各种索引,但无论我做什么,规划器都会进行嵌套的顺序扫描,对每对IP地址和前缀应用<<运算符。
有没有一种方法可以用索引或其他聪明的技巧来加速这个过程?(我可以求助于外部过程脚本,但我想知道在Postgres中是否可行。
谢谢!

vecaoik1

vecaoik11#

这是一个老问题,但在谷歌结果中很突出,所以在这里发表我的2美分:
在Postgres 9.4及更高版本中,你可以使用GIST索引来表示inet和cidr:https://www.postgresql.org/docs/current/static/gist-builtin-opclasses.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';
sd2nnvve

sd2nnvve2#

你看过ip4r吗?http://pgfoundry.org/projects/ip4r . IIRC,它对于INET相关的查找来说非常快。

icnyk63a

icnyk63a3#

结案了要快速完成任务,请执行以下操作:

  • 使用http://pgfoundry.org/projects/ip4r提供的ip 4 r类型,如用户bma所指出的。此类型支持Postgres(最高到Postgres 9.3)本机不支持的索引。
  • 不要直接使用ip 4 r类型,而是按照用户caskey的建议和ip 4 r文档中的说明,将其扩展为更小和更大的值:https://github.com/petere/ip4r-cvs/blob/master/README.ip4r#L187

考虑到以上情况,如果您对所有比较地址使用ip 4类型(假设您处理的是v4地址),那么规划器将利用这些列的索引。
谢谢你们的帮助!

at0kjp5o

at0kjp5o4#

在已经部署了确保CIDR不重叠的规则之后,我只使用了索引btree tablename(network(addr))
给定target作为输入检查如下:

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

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

相关问题