7

我正在使用 ipv4 和 ipv6 存储在 postgres db 中。

因为 ipv4 需要 32 位(4 字节)而 ipv6 需要 128(16 字节)位。那么为什么在 postgres CIDR 和 INET 数据类型中,IPV4 和 IPV6(8.1)分别存储为 12 字节和 24 字节。

对于 9.1,IPV4 和 IPV6 分别有 7 个字节和 19 个字节。

我不明白为什么它需要超过 16 个字节来存储 IPV6 和 4 个字节来存储 IPV4?

http://www.postgresql.org/docs/8.1/static/datatype-net-types.html

http://www.postgresql.org/docs/9.1/interactive/datatype-net-types.html

4

1 回答 1

12

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 表示。因此,您可以为每种类型添加 3 个字节(IP4:10,IP6:22)。除此之外,还有一个填充到下一个 4 字节边界。这为每种类型提供 2 个字节,总计 12 或 24 个字节。

这封邮件为较短版本的开发提供了一些启示。

于 2012-07-18T19:18:57.663 回答