gpt4 book ai didi

postgresql cidr 查找子 block

转载 作者:行者123 更新时间:2023-11-29 13:01:39 28 4
gpt4 key购买 nike

我正在寻找一种使用内置 cidr 类型从存储在 postgresql 中的 cidr block 获取直接子网络的方法。

示例数据库

CREATE TABLE nets (
id serial primary key,
net cidr
);
INSERT INTO nets (net) VALUES
('10.1.0.0/16'),
('10.1.0.0/20'),
('10.1.1.0/24'),
('10.1.1.8/29'),
('10.1.1.32/28'),
('10.2.15.0/24'),
('10.2.15.64/27')

所需的查询应该是 f.e.

  • 为搜索键 10.1.0.0/16 返回 10.1.0.0/20
  • 10.1.1.8/29 和 10.1.1.32/28 用于搜索关键字 10.1.1.0/24

我想到的是(http://sqlfiddle.com/#!15/2b4b5/1):

SELECT
id,
net
FROM
nets n
WHERE
net << '10.1.1.0/24' AND
'10.1.1.0/24' IN (
SELECT
net
FROM
nets
WHERE
net >> n.net
ORDER BY
net DESC
LIMIT 1
)
ORDER BY
net

这给出了期望的结果,但它没有缩放。即使数据库中只有几千个条目,这也会变得非常慢。

是否有另一种方法可以实现这一目标,而无需向数据库模型添加显式父/子关系?

最佳答案

更新:这是一个变种,由Nested set model转化而来,它可能会更快(主要是在 9.4+ 上使用 inet_ops GiST 索引):

SELECT c.id, c.net
FROM nets c
WHERE c.net << '10.1.1.0/24'
AND NOT EXISTS(
SELECT 1
FROM nets AS m
WHERE c.net << m.net AND m.net << '10.1.1.0/24'
);

原始答案:

一个简单的EXCEPT应该使用更大的输入集更好地扩展(它不会为每个子网络计算子计划):

(SELECT id, net
FROM nets
WHERE net << '10.1.1.0/24')
EXCEPT
(SELECT c.id, c.net
FROM nets p
JOIN nets c ON c.net << p.net
WHERE p.net << '10.1.1.0/24')
ORDER BY net;

注意:对于较小的输入集,EXCEPT变体可能比您的查询还要慢。

但是为了最大限度地提高性能(包括此查询和您的查询),您应该使用一些索引。

如果你有 PostgreSQL 9.4+,你应该使用新的 inet_ops GiST 索引:

CREATE INDEX nets_inet_net_gist ON nets USING gist (inet(net) inet_ops);

否则,您可以使用 network_ops b树索引:

CREATE INDEX nets_inet_net_btree ON nets USING btree (inet(net) network_ops);

同时 inet_ops可以直接使用<<运算符(operator),network_ops会将你的表情转换成类似的东西:

Index Cond: (((net)::inet > '10.1.1.0/24'::inet) AND ((net)::inet <= '10.1.1.255'::inet))

关于postgresql cidr 查找子 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28388609/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com