本文介绍了ip4r
插件的背景信息、数据类型以及使用方法等内容。
前提条件
支持的PolarDB PostgreSQL版(兼容Oracle)的版本如下:
Oracle语法兼容 2.0(内核小版本2.0.14.13.0及以上)
Oracle语法兼容 1.0(内核小版本1.1.36及以上)
您可通过如下语句查看PolarDB PostgreSQL版(兼容Oracle)的内核小版本号:
SHOW polar_version;
背景信息
ip4r
是PolarDB PostgreSQL版(兼容Oracle)支持的一款第三方插件,支持存储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
:输入形式必须满足ip4
或ip6
其中之一。
针对以上三种数据类型,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.200
、192.0.2.0/24
等价于192.0.2.0-192.0.2.255
。ip6r
:用于存储IPv6地址范围类型的数据,例如2001::1234-2001::2000:0000
、2001::/112
等价于2001::-2001::ffff
。iprange
:输入形式必须满足ip4r
或ip6r
其中之一。
针对以上三种数据类型,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;