存储与类型差异
PostgreSQL 原生支持 inet 和 cidr 类型,自动处理 IPv4/IPv6 转换和校验,适合网络运算场景。MySQL 需手动使用 VARBINARY(16) 配合 INET6_ATON/INET6_NTOA 函数存储,缺乏原生网络操作支持。
核心区别对比
| 特性 | PostgreSQL (使用 inet 或 cidr 类型) | MySQL (使用 VARBINARY 搭配函数) |
| 存储类型 | 原生网络类型:inet(地址/子网)或 cidr(网络/子网)。 | 通用类型:VARBINARY(16) 存储二进制格式的地址,或 VARCHAR 存储字符串。 |
| 优势 | 语义清晰、存储效率高、支持原生索引、可直接使用网络操作符(如包含 <@)。 | 紧凑高效(VARBINARY(16))、向后兼容性好、函数操作简单。 |
| 劣势 | 如果不熟悉 inet 类型,可能需要学习新的操作符。 | 需要使用函数进行存储和读取时的转换,查询时必须依赖函数。 |
PostgreSQL 示例:
CREATE TABLE network_devices (
device_id SERIAL PRIMARY KEY,
ip_address inet NOT NULL,
subnet cidr
);
MySQL 示例:
CREATE TABLE network_devices (
device_id BIGINT AUTO_INCREMENT PRIMARY KEY,
ip_address VARBINARY(16) NOT NULL,
subnet VARBINARY(16)
);
插入与查询操作
PostgreSQL 直接支持文本形式插入和网络运算符查询。MySQL 需通过函数转换,且子网查询需手动处理。
PostgreSQL 插入与查询:
-- 插入
INSERT INTO network_devices (ip_address, subnet)
VALUES ('2001:db8::1', '2001:db8::/32');
-- 子网查询
SELECT * FROM network_devices
WHERE ip_address <<= subnet;
MySQL 插入与查询:
-- 插入
INSERT INTO network_devices (ip_address, subnet)
VALUES (INET6_ATON('2001:db8::1'), INET6_ATON('2001:db8::'));
-- 精确匹配查询
SELECT INET6_NTOA(ip_address) FROM network_devices
WHERE ip_address = INET6_ATON('2001:db8::1');
子网查询实现对比
PostgreSQL 通过内置运算符(如 <<=)高效完成子网匹配。MySQL 需依赖位运算或额外字段。
PostgreSQL 子网查询:
-- 查找属于某子网的 IP
SELECT * FROM network_devices
WHERE ip_address <<= '192.168.0.0/16';
MySQL 位运算方案:
-- 假设前缀长度为 /64
SELECT * FROM network_devices
WHERE SUBSTRING(ip_address, 1, 8) = SUBSTRING(INET6_ATON('2001:db8::'), 1, 8);
索引优化建议
PostgreSQL 使用 GiST 索引加速子网查询,MySQL 需额外生成列配合索引。
PostgreSQL 索引:
-- 精确匹配索引
CREATE INDEX idx_ip ON network_devices (ip_address);
-- 子网查询索引
CREATE INDEX idx_subnet_gist ON network_devices USING GIST (subnet);
MySQL 生成列方案:
-- 添加生成列存储网络基址
ALTER TABLE network_devices ADD COLUMN network_base VARBINARY(16)
GENERATED ALWAYS AS (SUBSTRING(ip_address, 1, 8)) STORED;
-- 创建索引
CREATE INDEX idx_network_base ON network_devices (network_base);
常用函数对比
PostgreSQL 函数示例:
-- 获取 IP 版本和掩码长度
SELECT family(ip_address), masklen(subnet) FROM network_devices;
-- 修改掩码长度
UPDATE network_devices SET subnet = set_masklen(subnet, 24);
MySQL 函数示例:
-- 二进制转文本
SELECT INET6_NTOA(ip_address) FROM network_devices;
-- 计算前缀长度(需自定义函数)
性能优化建议:
- MySQL:对高频子网查询,预计算并存储网络基址和前缀长度。
- PostgreSQL:优先使用
inet类型,充分利用 GiST 索引和内置运算符。

被折叠的 条评论
为什么被折叠?



