postgresql数据库网络地址存储探索(inet)
生活随笔
收集整理的這篇文章主要介紹了
postgresql数据库网络地址存储探索(inet)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
問題背景
數據庫審核過程中發現有存儲ip的字段類型為varchar(50)、想到postgresql有專門的存儲ip類型。然而存在即合理、所以主要對比varchar和inet存儲ip的不同。
網絡地址類型
| 名字 | 存儲空間 | 描述 |
|---|---|---|
| cidr | 7 或 19 字節 | IPv4 或 IPv6 網絡 |
| inet | 7 或 19 字節 | IPv4 或 IPv6 主機和網絡 |
| macaddr | 6 字節 | 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做簡單的加減。
總結
以上是生活随笔為你收集整理的postgresql数据库网络地址存储探索(inet)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从中国矢量图筛选出江苏省行政区划图
- 下一篇: nullptr、NULL、null和0