PostgreSQL: Hstore 数据类型使用介绍

hstore 数据类型作为 Extension 模块, 在之前版本已经有了,之前大概知道概念,一直没怎么研究,今天做了些测试。简单的说 hstore 数据类型用来存储具有多个属性值的数据,模板如 key => value , key 代表存储的属性, values 为相应属性对应的值,一个简单的 hstore 例子如下:

Hstore 示例

1
2
3
4
5
6
7
8
9
10
skytf=> select 'a=>1,b=>2'::hstore;  
hstore
--------------------
"a"=>"1", "b"=>"2"
(1 row)
skytf=> select hstore('a=>1,b=>2');
hstore
--------------------
"a"=>"1", "b"=>"2"
(1 row)

Hstore 操作符演示

2.1 查询属性(key) a 的值;

1
2
3
4
5
skytf=> select hstore('a=>1,b=>2') -> 'a';  
?column?
----------
1
(1 row)

2.2 判断是否包含指定属性(key),如果包含,返回 t

1
2
3
4
5
6
7
8
9
10
skytf=> select hstore('a=>1,b=>2') ? 'a';  
?column?
----------
t
(1 row)
skytf=> select hstore('a=>1,b=>2') ? 'c';
?column?
----------
f
(1 row)

2.3 判断左边的 hstore 是否包含右边的 hstore ,如果包含,返回 t。

1
2
3
4
5
6
7
8
9
10
skytf=> select hstore('a=>1,b=>2') @> 'a=>1'::hstore;  
?column?
----------
t
(1 row)
skytf=> select hstore('a=>1,b=>2') @> 'a=>2'::hstore;
?column?
----------
f
(1 row)

备注:更多 hstore 函数和操作符,详见本文的附录部分。

Hstore 函数演示

3.1 array 类型转换成 hstore

1
2
3
4
5
skytf=> select hstore(ARRAY['a','1','b','2']);  
hstore
--------------------
"a"=>"1", "b"=>"2"
(1 row)

3.2 将两个 array 类型数据转换成 hstore 类型,比较难表达,看例子理解。

1
2
3
4
5
skytf=> select hstore(ARRAY['a','b','c'], ARRAY['1','2','3']);  
hstore
------------------------------
"a"=>"1", "b"=>"2", "c"=>"3"
(1 row)

备注:看到了吧,非常强大。
3.3 将 hstore 类型数据的 key 转换成 array

1
2
3
4
5
skytf=> select akeys('a=>1,b=>2');  
akeys
-------
{a,b}
(1 row)

3.4 将 hstore 类型数据的 key 转换成 结果集

1
2
3
4
5
6
skytf=> select skeys('a=>1,b=>2');  
skeys
-------
a
b
(2 rows)

3.5 将 hstore 类型数据的 values 转换成 array

1
2
3
4
5
skytf=> select avals('a=>1,b=>2');  
avals
-------
{1,2}
(1 row)

3.6 将 hstore 类型数据的 values 转换成 结果集

1
2
3
4
5
6
skytf=> select svals('a=>1,b=>2');  
svals
-------
1
2
(2 rows)

3.7 删除一个属性

1
2
3
4
5
skytf=> select delete(hstore('a=>1,b=>2'),'b');  
delete
----------
"a"=>"1"
(1 row)

3.8 增加一个属性

1
2
3
4
5
skytf=> select hstore('a=>1,b=>2') || 'c=>3';  
?column?
------------------------------
"a"=>"1", "b"=>"2", "c"=>"3"
(1 row)

备注:先演示这么多吧,更多内容,参考本文的附。

Example1: Hstore 使用

4.1 环境
PG版本:PostgreSQL 9.2
OS版本:Red Hat Enterprise Linux Server release 6.2
4.2 创建 hstore 外部模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
skytf=> /c skytf postgres;  
You are now connected to database "skytf" as user "postgres".

skytf=# create extension hstore;
CREATE EXTENSION

skytf=# /c skytf skytf;
You are now connected to database "skytf" as user "skytf".

skytf=> /dT hstore;
List of data types
Schema | Name | Description
--------+--------+-------------
public | hstore |
(1 row)

4.3 创建测试表,并生成测试数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
skytf=> create table tbl_role(id serial primary key,role_name varchar(32), exp int8, wealth int8, status char(1));  
NOTICE: CREATE TABLE will create implicit sequence "tbl_role_id_seq" for serial column "tbl_role.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tbl_role_pkey" for table "tbl_role"
CREATE TABLE
skytf=> insert into tbl_role(role_name,exp,wealth) select 'user_' || generate_series(1,100000) ,generate_series(1,100000),generate_series(100001,200000);
INSERT 0 100000

skytf=> select * from tbl_role limit 3;
id | role_name | exp | wealth | status
----+-----------+-----+--------+--------
1 | user_1 | 1 | 100001 |
2 | user_2 | 2 | 100002 |
3 | user_3 | 3 | 100003 |
(3 rows)

备注:上面创建一张角色信息表,属性值有 exp:经验值, wealth:财富值等。

4.4 增加 hstore 数据类型

1
2
3
4
5
6
7
8
9
10
skytf=> alter table tbl_role add column attr hstore;  
ALTER TABLE
skytf=> update tbl_role set attr=('exp=>' || exp || ', wealth=>' || wealth )::hstore;UPDATE 100000
skytf=> select * from tbl_role limit 3;;
id | role_name | exp | wealth | status | attr
----+-----------+-----+--------+--------+---------------------------------
22 | user_22 | 22 | 100022 | | "exp"=>"22", "wealth"=>"100022"
23 | user_23 | 23 | 100023 | | "exp"=>"23", "wealth"=>"100023"
24 | user_24 | 24 | 100024 | | "exp"=>"24", "wealth"=>"100024"
(3 rows)

4.5 创建索引

1
2
skytf=> create index concurrently idx_tbl_role_attr on tbl_role using GIST ( attr);  
CREATE INDEX

备注: hstore 类型的数据支持 GIN,GIST 索引扫描的操作符有 @>, ?, ?& 和 ?|
4.6 测试:查询 hstore 子元素 exp 值为 22 的记录

1
2
3
4
5
6
7
8
9
skytf=> select id,role_name,attr,attr -> 'exp' From tbl_role where attr @> 'exp=>22';  
id | role_name | attr | ?column?
----+-----------+---------------------------------+----------
22 | user_22 | "exp"=>"22", "wealth"=>"100022" | 22
(1 row)
skytf=> select id,role_name,attr,attr -> 'wealth' From tbl_role where attr @> 'wealth=>100001';
id | role_name | attr | ?column?
----+-----------+--------------------------------+----------
1 | user_1 | "exp"=>"1", "wealth"=>"100001" | 100001

4.7 执行计划:

1
2
3
4
5
6
7
8
9
10
skytf=> explain analyze select id,role_name,attr,attr -> 'exp' From tbl_role where attr @> 'exp=>22';  
QUERY PLAN
-------------------------------------------------------------------------------------------
Bitmap Heap Scan on tbl_role (cost=5.36..347.63 rows=100 width=54) (actual time=3.267..7.111 rows=1 loops=1)
Recheck Cond: (attr @> '"exp"=>"22"'::hstore)
Rows Removed by Index Recheck: 1545
-> Bitmap Index Scan on idx_tbl_role_attr (cost=0.00..5.33 rows=100 width=0) (actual time=2.813..2.813 rows=1546 loops=1)
Index Cond: (attr @> '"exp"=>"22"'::hstore)
Total runtime: 7.185 ms
(6 rows)

备注:消耗 7 ms 左右,这个查询速度并不很快。

Example2: 将结果集转换成 hstore 类型

5.1 测试表

1
2
3
4
5
6
skytf=> select * From test_1;  
id | name
----+--------
1 | francs
2 | fpzhou
(2 rows)

5.2 将结果集转换成 hstore 类型输出

1
2
3
4
5
6
7
8
9
10
11
12
skytf=> select hstore(test_1) From test_1;  
hstore
-----------------------------
"id"=>"1", "name"=>"francs"
"id"=>"2", "name"=>"fpzhou"
(2 rows)

skytf=> select hstore(test_1) From test_1 where id=1;
hstore
-----------------------------
"id"=>"1", "name"=>"francs"
(1 row)

附: Hstore 函数和操作符

总结

hstore 适用于拥有多个属性值的对像,同时这些属性值查询并不非常频繁的场合,根据上面的测试,在 10 万数据中,根据元素属性值查询需要7ms 左右,这个速度已经算慢的了。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/237899.html

(0)
上一篇 2022年1月29日
下一篇 2022年1月29日

相关推荐

发表回复

登录后才能评论