ip4r(网络地址存储)

本文介绍了ip4r插件的背景信息、数据类型以及使用方法等内容。

前提条件

支持的PolarDB PostgreSQL版的版本如下:

  • PostgreSQL 14(内核小版本14.9.13.0及以上)

  • PostgreSQL 11(内核小版本1.1.36及以上)

说明

您可通过如下语句查看PolarDB PostgreSQL版的内核小版本号:

  • PostgreSQL 14

    SELECT version();
  • PostgreSQL 11

    SHOW polar_version;

背景信息

ip4rPolarDB PostgreSQL版支持的一款第三方插件,支持存储IPv4或IPv6数据类型。与PostgreSQL提供的相关内置数据类型inet/cidr不同,ip4r支持对包含操作符>>=进行索引扫描。除此之外,ip4r相对于PostgreSQL内置的网络数据类型还有以下特点:

  • 语义清晰:将网络块网络块内的特定IP地址两种语义进行了明确区分。

  • 开销更低:PostgreSQL为支持存储IPv6数据而使用了变长数据类型,对明确需要存储IPv4数据的场景来说是不小的开销。ip4r对单一地址数据将使用定长数据类型。

数据类型

ip4r提供了丰富的数据类型来支持存储、表示IPv4或IPv6数据:

数据类型

说明

ip4

单一IPv4地址。

ip4r

任意IPv4地址范围。

ip6

单一IPv6地址。

ip6r

任意IPv6地址范围。

ipaddress

单一IPv4或IPv6地址。

iprange

任意IPv4或IPv6地址范围。

单一地址数据类型及其类型转换

以下三种数据类型用于存储单一IP地址数据:

  • ip4:输入形式必须满足nnn.nnn.nnn.nnn,其实际存储的数据为32位无符号整型数据。

  • ip6:输入形式必须是IPv6地址的标准十六进制表示形式,其实际存储的数据为两个64位数据。

  • ipaddress:输入形式必须满足ip4ip6其中之一。

针对以上三种数据类型,ip4r提供了相应的类型转换,具体规则如下:

说明

下表中的ipX表示上述三种类型其中之一。

原类型

目标类型

格式

ipX

text

text(ipX) or ipX::text (explicit)

text

ipX

ipX(text) or text::ipX (explicit)

ipX

cidr

cidr(ipX) or ipX::cidr (assignment)

inet

ipX

ipX(inet) or inet::ipX (assignment)

ipX

numeric

to_numeric(ipX) or ipX::numeric (explicit)

numeric

ipX

ipX(numeric) or bigint::ipX (explicit)

ip4

bigint

to_bigint(ip4) or ip4::bigint (explicit)

bigint

ip4

ip4(bigint) or bigint::ip4 (explicit)

ip4

float8

to_double(ip4) or ip4::float8 (explicit)

float8

ip4

ip4(float8) or float8::ip4 (explicit)

ipX

varbit

to_bit(ipX) or ipX::varbit (explicit)

bit(32)

ip4

ip4(bit) or bit::ip4 (explicit)

bit(128)

ip6

ip6(bit) or bit::ip6 (explicit)

varbit

ipX

ipX(varbit) or varbit::ipX (explicit)

ipX

bytea

to_bytea(ipX) or ipX::bytea (explicit)

bytea

ipX

ipX(bytea) or bytea::ipX (explicit)

ipX

ipXr

ipXr(ipX) or ipX::ipXr (implicit)

ip4

ipaddress

ipaddress(ip4) or ip4::ipaddress (implicit)

ip6

ipaddress

ipaddress(ip6) or ip6::ipaddress (implicit)

ipaddress

ip4

ip4(ipaddress) or ipaddress::ip4 (assignment)

ipaddress

ip6

ip6(ipaddress) or ipaddress::ip6 (assignment)

地址范围数据类型及其类型转换

以下三种数据类型用于存储一段IP地址范围的数据:

  • ip4r:用于存储IPv4地址范围类型的数据,例如192.0.2.100-192.0.2.200192.0.2.0/24等价于192.0.2.0-192.0.2.255

  • ip6r:用于存储IPv6地址范围类型的数据,例如2001::1234-2001::2000:00002001::/112等价于2001::-2001::ffff

  • iprange:输入形式必须满足ip4rip6r其中之一。

针对以上三种数据类型,ip4r提供了相应的类型转换,具体规则如下:

说明

下表中的ipXr表示上述三种类型其中之一。

原类型

目标类型

格式

ipX

ipXr

ipXr(ipX) or ipX::ipXr (implicit)

ipXr

text

text(ipXr) or ipXr::text (explicit)

text

ipXr

ipXr(text) or text::ipXr (explicit)

ipXr

cidr

cidr(ipXr) or ipXr::cidr (explicit)

cidr

ipXr

ipXr(cidr) or cidr::ipXr (assignment)

ipXr

varbit

to_bit(ipXr) or ipXr::varbit (explicit)

varbit

ip4r

ip4r(varbit) or varbit::ip4r (explicit)

varbit

ip6r

ip6r(varbit) or varbit::ip6r (explicit)

使用方法

创建插件

CREATE EXTENSION ip4r;

创建测试表并导入数据

CREATE TABLE ipranges (r iprange, r4 ip4r, r6 ip6r);
INSERT INTO ipranges
    SELECT r, null, r
    FROM (
        SELECT ip6r(regexp_replace(ls, E'(....(?!$))', E'\\1:', 'g')::ip6,
               regexp_replace(substring(ls FOR n + 1) || substring(us FROM n + 2),
               E'(....(?!$))', E'\\1:', 'g')::ip6) AS r
        FROM (
            SELECT md5(i || ' lower 1') AS ls,
                   md5(i || ' upper 1') AS us,
                   (i % 11) + (i/11 % 11) + (i/121 % 11) AS n
            FROM generate_series(1,13310) i) s1) s2;

创建GiST索引

CREATE INDEX ipranges_r ON ipranges USING gist (r);

使用包含操作符

EXPLAIN (COSTS OFF) SELECT * FROM ipranges WHERE r >>= '5555::' ORDER BY r;

返回结果如下:

                     QUERY PLAN                      
-----------------------------------------------------
 Sort
   Sort Key: r
   ->  Bitmap Heap Scan on ipranges
         Recheck Cond: (r >>= '5555::'::iprange)
         ->  Bitmap Index Scan on ipranges_r
               Index Cond: (r >>= '5555::'::iprange)
(6 rows)

卸载插件

DROP EXTENSION ip4r;