在 Postgres 数据库中,我需要过滤表 A 中的一组数十万行,方法是仅包含行中 IP 地址列(inet 类型)与数千个 IP 地址块(类型cidr)在另一个表B中。我已经尝试了第一个表中inet地址和第二个表中的cidr范围的各种索引,但无论我做什么,规划器都会进行嵌套顺序扫描,将<<运算符应用于每对 IP 地址和前缀。
有没有办法通过索引或其他巧妙的技巧来加快速度?(我可以求助于外部程序脚本,但我想知道它在 Postgres 中是否可行。)
谢谢!
在 Postgres 数据库中,我需要过滤表 A 中的一组数十万行,方法是仅包含行中 IP 地址列(inet 类型)与数千个 IP 地址块(类型cidr)在另一个表B中。我已经尝试了第一个表中inet地址和第二个表中的cidr范围的各种索引,但无论我做什么,规划器都会进行嵌套顺序扫描,将<<运算符应用于每对 IP 地址和前缀。
有没有办法通过索引或其他巧妙的技巧来加快速度?(我可以求助于外部程序脚本,但我想知道它在 Postgres 中是否可行。)
谢谢!
这是一个古老的问题,但在谷歌搜索结果中很突出,所以在这里发布我的 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';
结案。为了加快速度,请执行以下操作:
正如用户 bma 所指出的,使用http://pgfoundry.org/projects/ip4r提供的 ip4r 类型。这种类型支持 Postgres(最高到 Postgres 9.3)本地不支持的索引。
不要直接使用 ip4r 类型,而是按照用户 caskey 的建议和 ip4r 文档中提到的将其扩展为上下值:https ://github.com/petere/ip4r-cvs/blob/master/README.ip4r# L187
鉴于上述情况,如果您对所有比较地址使用类型 ip4(假设您正在处理 v4 地址),那么规划器将利用这些列上的索引。
谢谢你们的帮助,伙计们!
你看过ip4r吗? http://pgfoundry.org/projects/ip4r。IIRC,对于与 INET 相关的查找,它真的很快。