postgres-数据库ip地址存储探索

问题背景

数据库审核过程中发现有存储ip的字段类型为varchar(50)、想到postgresql有专门的存储ip类型。然而存在即合理、所以主要对比varchar和inet存储ip的不同。

网络地址类型

名字存储空间描述
cidr7 或 19 字节IPv4 或 IPv6 网络
inet7 或 19 字节IPv4 或 IPv6 主机和网络
macaddr6 字节MAC 地址

cidr默认是存储了子网掩码、而inet可以不存储、macaddr用于存储MAC地址

创建测试表、生成测试数据

postgres=# create table t_ip_test(c_bh char(32),ip_start inet,ip_end inet);
CREATE TABLE
postgres=# insert into t_ip_test values(replace(CAST(uuid_generate_v4()as varchar), '-', ''),'192.168.1.1','192.230.254.254');
INSERT 0 1
--创建测试表
postgres=# create table t_ip(c_bh char(32),inet_ip inet,c_ip varchar (50));
CREATE TABLE
--生成测试数据192.168.1.1-192.230.254.254连续的ip
postgres=# insert into t_ip
postgres-# select
postgres-# replace(CAST(uuid_generate_v4()as varchar), '-', ''),
postgres-# generate_series(0,ip_end-ip_start)+ip_start as inet_ip,
postgres-# (generate_series(0,ip_end-ip_start)+ip_start) as c_ip
postgres-#from t_ip_test;
INSERT 0 4128254
--添加主键
postgres=# alter table public.t_ip ADD PRIMARY KEY ("c_bh");
ALTER TABLE

总共生成400W+数据

创建索引

--inet类型
postgres=# create index idx_t_ip_inet_ip on t_ip(inet_ip);
CREATE INDEX
--varchar类型
postgres=# create index idx_t_ip_c_ip on t_ip(c_ip);
CREATE INDEX

对比表大小、索引大小

--表大小
postgres=# select pg_size_pretty(pg_relation_size('t_ip')); 
 pg_size_pretty 
----------------
 365 MB
(1 row)
--索引大小
postgres=# select indexrelname, pg_size_pretty(pg_relation_size(indexrelname::varchar)) 
postgres-# from pg_stat_user_indexes where schemaname = 'public';
   indexrelname   | pg_size_pretty 
------------------+----------------
 t_ip_pkey        | 233 MB
 idx_t_ip_inet_ip | 88 MB
 idx_t_ip_c_ip    | 159 MB
(3 rows)

可以看到idx_tip_cip比idx_t_ip_inet_ip大了接近一倍

网络地址能自动验证ip正确性

--测试192.168.1.256
postgres=# insert into t_ip(c_bh,inet_ip,c_ip) values(replace(CAST(uuid_generate_v4()as varchar), '-', ''),'192.168.1.256','192.168.1.255');
ERROR:  invalid input syntax for type inet: "192.168.1.256"
LINE 1: ...lace(CAST(uuid_generate_v4()as varchar), '-', ''),'192.168.1...'
​
postgres=# insert into t_ip(c_bh,inet_ip,c_ip) values(replace(CAST(uuid_generate_v4()as varchar), '-', ''),'192.168.1.255','192.168.1.256')
postgres-# ;
INSERT 0 1

可以看到inet类型能够自动识别IP是否合理、而varchar会将错误的ip插入数据库

inet类型查询某个段、某个范围的ip可以走索引

--查询某个段的ip 使用inet类型
postgres=# explain analyze select c_bh,inet_ip,c_ip from t_ip where inet_ip <<= inet '192.168.12/24';
                                                         QUERY PLAN                                                         
----------------------------------------------------------------------------------------------------------------------------
-
 Index Scan using idx_t_ip_inet_ip on t_ip  (cost=0.43..17.98 rows=161 width=58) (actual time=0.054..0.659 rows=256 loops=1)
   Index Cond: ((inet_ip >= '192.168.12.0/24'::inet) AND (inet_ip <= '192.168.12.255'::inet))
   Filter: (inet_ip <<= '192.168.12.0/24'::inet)
 Planning time: 1.531 ms
 Execution time: 1.128 ms
(5 rows)
​
​
--查询某个段的ip 使用varchar类型
postgres=# explain analyze select c_bh,inet_ip,c_ip from t_ip where c_ip like '192.168.12.%'; 
                                                QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
 Seq Scan on t_ip  (cost=0.00..98381.98 rows=413 width=58) (actual time=0.761..1063.944 rows=256 loops=1)
   Filter: ((c_ip)::text ~~ '192.168.12.%'::text)
   Rows Removed by Filter: 4127998
 Planning time: 0.519 ms
 Execution time: 1064.433 ms
(5 rows)
​
--查询某个范围的ip inet类型
postgres=# explain analyze select c_bh,inet_ip,c_ip from t_ip where inet_ip >= inet '192.230.253.200' and inet_ip <'192.230.254.7';
                                                        QUERY PLAN                                                        
--------------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_t_ip_inet_ip on t_ip  (cost=0.43..9.69 rows=63 width=58) (actual time=0.042..0.181 rows=63 loops=1)
   Index Cond: ((inet_ip >= '192.230.253.200'::inet) AND (inet_ip < '192.230.254.7'::inet))
 Planning time: 0.378 ms
 Execution time: 0.324 ms
(4 rows)
​
--使用varchar类型好像并没有什么好的办法查询一个范围

在inet类型上面创建btree索引、可以用上索引。

inet类型针对网络类型的操作更丰富(<、<=、=、>...)

--对ip做加减
postgres=# select inet'192.168.1.1'+100;
   ?column?    
---------------
 192.168.1.101
(1 row)
​
--查询两个ip之间有多少个ip
postgres=# select inet'192.168.2.1'-inet'192.168.1.1';
 ?column? 
----------
      256
(1 row)
​
--减去100个ip后的ip
postgres=# select inet'192.168.1.254'-100;
   ?column?    
---------------
 192.168.1.154
(1 row)

masklen:获取子网掩码长度

--inet获取子网掩码
postgres=# select masklen('192.168.1.1');
 masklen 
---------
      32
(1 row)
​
postgres=# select masklen('192.168.1.1/24');
 masklen 
---------
      24
(1 row)

网络类型更多操作连接

结语

推荐使用网络地址存储ip、PostgreSql提供的网络数据类型有以下优势:

1.创建索引更省空间

2.能够自动校验ip的正确

3.统计某段或者某个区间可以走索引、而varcahr并不能很好的统计某个区间

4.在做统计的时候网络类型操作更加丰富、对ip做简单的加减。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Postgres-XL是一个强大的分布式数据库集群,可以在大规模数据环境中提供高可用性和高性能。使用Postgres-XL集群,您可以将数据分布在多个节点上,并平衡负载以提高系统吞吐量。 手动配置Postgres-XL集群需要以下步骤: 1. 安装Postgres-XL:首先,您需要在每个节点上安装Postgres-XL软件。可以通过源代码编译或使用预编译的软件包进行安装。确保每个节点的Postgres-XL版本一致。 2. 配置Postgres-XL集群:在每个节点上,您需要编辑Postgres-XL的配置文件来设置集群的参数。配置文件通常位于“$PGXL_HOME/pgxc_ctl/pgxc_ctl.conf”。在配置文件中,您需要指定每个节点的主机名和端口号,以及其他相关参数,如共享存储的路径和主节点的IP地址。 3. 初始化集群:一旦配置文件正确设置,您可以使用pgxc_ctl工具来初始化集群。该工具位于“$PGXL_HOME/pgxc_ctl/pgxc_ctl”。在pgxc_ctl命令行中,您可以执行“init all”命令来初始化集群。此操作将创建必要的数据库对象和配置表,以管理集群。 4. 启动集群:一旦初始化完成,您可以使用pgxc_ctl工具来启动集群。在pgxc_ctl命令行中,您可以执行“start all”命令来启动集群。此操作将启动每个节点上的Postgres-XL进程,并将其连接到集群。 5. 验证集群:一旦集群启动,您可以使用任何标准的PostgreSQL客户端工具连接到集群,并执行SQL查询。您还可以使用pgxc_ctl工具来检查所有节点的状态,并确保它们正常运行。 6. 扩展集群:如果您需要扩展Postgres-XL集群以支持更多的节点和更大的数据库负载,您可以使用pgxc_ctl工具来添加新的节点和重新平衡数据。具体的扩展步骤取决于您的集群架构和需求。 总结而言,手动配置Postgres-XL集群需要安装软件、编辑配置文件、初始化集群、启动集群、验证集群以及可能的扩展集群。这些步骤可以确保您的Postgres-XL集群正确设置并可用于处理大规模数据工作负载。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值