在Postgres数据库中,我需要在表A中过滤一组数十万行,只包含那些行中IP地址列(类型为inet)与几千个IP地址块中的任何一个匹配的行(在类型cidr中)在另一个表B中。我在第一个表中的inet地址上尝试了各种索引,在第二个表中尝试了cidr范围,但无论我做什么,规划器都进行嵌套顺序扫描,应用< ;<运营商到每对IP地址和前缀。
有没有办法通过索引或其他聪明的技巧加快速度? (我可以使用外部程序脚本,但我想知道它是否在Postgres中可行。)
谢谢!
答案 0 :(得分:5)
这是一个老问题,但在谷歌搜索结果中很突出,所以在这里发布我的2美分:
使用Postgres 9.4及更高版本,您可以对inet和cidr使用GIST索引:https://www.postgresql.org/docs/current/static/gist-builtin-opclasses.html
E.g。以下查询将使用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';
答案 1 :(得分:2)
案件结案。为了加快速度,请执行以下操作:
使用http://pgfoundry.org/projects/ip4r提供的ip4r类型,如用户bma所指出的那样。这种类型支持索引,Postgres(直到Postgres 9.3)原生的不支持索引。
不要直接使用ip4r类型,而是按照用户caskey的建议将其扩展为较低和较高的值,并在ip4r docs中提及:https://github.com/petere/ip4r-cvs/blob/master/README.ip4r#L187
鉴于上述情况,如果您使用的是所有比较地址的类型ip4(假设您正在处理v4地址),则计划程序将利用这些列上的索引。
感谢您的帮助,伙计们!
答案 2 :(得分:1)