由于IPv6需要128位(16字节),为什么在Postgres CIDR数据类型中存储为24字节(8.1版本)和19字节(9.1版本)?

8
我正在使用IPv4和IPv6存储在Postgres数据库中。
由于IPv4需要32位(4字节),IPv6需要128位(16字节),那么为什么在Postgres中CIDR和INET数据类型的存储分别为12字节和24字节,用于IPv4和IPv6(8.1)?
在9.1版本中,IPv4和IPv6分别为7字节和19字节。
我不明白为什么需要额外的字节来存储IPv6超过16字节,IPv4超过4字节?详情请参考:http://www.postgresql.org/docs/8.1/static/datatype-net-types.htmlhttp://www.postgresql.org/docs/9.1/interactive/datatype-net-types.html

网络掩码位至少需要+1字节,例如"10.1.0.0/8"对于10.1.0.0和子网掩码255.0.0.0是有效的。 - Alex K.
1个回答

13

IP数据类型的源代码如下所示:

typedef struct
{
    unsigned char family;       /* PGSQL_AF_INET or PGSQL_AF_INET6 */
    unsigned char bits;         /* number of bits in netmask */
    unsigned char ipaddr[16];   /* up to 128 bits of address */
} inet_struct;

这意味着除了ipaddr中的“原始”数据(IP4需要4个字节,IP6需要16个字节)外,还有一个字节用于网络掩码和一个字节用于地址族(基本上是IP4/IP6的开关)。

此外,同一文件中还提到了varlena开销:

/*
 * Both INET and CIDR addresses are represented within Postgres as varlena
 * objects, ie, there is a varlena header in front of the struct type
 * depicted above.  This struct depicts what we actually have in memory
 * in "uncompressed" cases.  Note that since the maximum data size is only
 * 18 bytes, INET/CIDR will invariably be stored into tuples using the
 * 1-byte-header varlena format.  However, we have to be prepared to cope
 * with the 4-byte-header format too, because various code may helpfully
 * try to "decompress" 1-byte-header datums.
 */
typedef struct
{
    char        vl_len_[4];     /* Do not touch this field directly! */
    inet_struct inet_data;
} inet;

因此,IP4的方程式如下:

1 byte varlena
1 byte address family
1 byte netmask
4 raw bytes
=========== 
7 byte total

对于IP6,同样的公式会给出19个字节。

编辑旧版PostgreSQL只有4字节的varlena表示。因此,每种类型(IP4:10,IP6:22)可以增加3个字节。另外,还要填充到下一个4字节边界。这每种类型是2个字节,总共为12或24个字节。

该邮件解释了更短版本的开发情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接