日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

postgresql数据库网络地址存储探索(inet)

發布時間:2023/12/31 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 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)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。