微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

【原创】PostgreSQL hstore 列性能提升一例

Postgresql 支持hstore 来存放KEY->VALUE这类数据, 其实也类似于ARRAY或者JSON类型。 要高效的使用这类数据,当然离不开高效的索引。我们今天就来看看两类不同的索引对于同一种检索请求的性能问题。


假如我们有这样一个原始表,基于str1字段有一个BTREE索引。

t_girl=#\dstatus_check;
Table"ytt.status_check"
Column|Type|Modifiers
--------+-----------------------+-----------
is_yes|boolean|notnull
str1|charactervarying(20)|notnull
str2|charactervarying(20)|notnull
Indexes:
"index_status_check_str1"btree(str1)



里面有10W条记录。 数据大概如下,

t_girl=#select*fromstatus_checklimit2;
is_yes|str1|str2
--------+------+----------------------
f|0|cfcd208495d565ef66e7
t|1|c4ca4238a0b923820dcc
(2rows)
Time:0.617ms
t_girl=#


存放hstore类型的status_check_hstore 表结构,基于str1_str2字段有一个GIST索引。

Table"ytt.status_check_hstore"
Column|Type|Modifiers
-----------+---------+-----------
is_yes|boolean|
str1_str2|hstore|
Indexes:
"idx_str_str2_gist"gist(str1_str2)
t_girl=#select*fromstatus_check_hstorelimit2;
is_yes|str1_str2
--------+-----------------------------
f|"0"=>"cfcd208495d565ef66e7"
t|"1"=>"c4ca4238a0b923820dcc"
(2rows)
Time:39.874ms


接下来我们要得到跟查询原始表一样的结果,当然原始表的查询非常高效。 表语句以及结果如下,

t_girl=#select*fromstatus_checkwherestr1in('10','23','33');
is_yes|str1|str2
--------+------+----------------------
t|10|d3d9446802a44259755d
t|23|37693cfc748049e45d87
f|33|182be0c5cdcd5072bb18
(3rows)
Time:0.690ms


上面的语句用了不到1毫秒。


接下来我们对hstore表进行查询

t_girl=#selectis_yes,skeys(str1_str2),svals(str1_str2)fromstatus_check_hstorewherestr1_str2?|array['10','33'];
is_yes|skeys|svals
--------+-------+----------------------
t|10|d3d9446802a44259755d
t|23|37693cfc748049e45d87
f|33|182be0c5cdcd5072bb18
(3rows)
Time:40.256ms

我的天,比原始表的查询慢了几十倍。


看下查询计划,把所有行都扫描了一遍。

QUERYPLAN
-----------------------------------------------------------------------------------
BitmapHeapScanonstatus_check_hstore(cost=5.06..790.12rows=100000width=38)
RecheckCond:(str1_str2?|'{10,23,33}'::text[])
->BitmapIndexScanonidx_str_str2_gist(cost=0.00..5.03rows=100width=0)
IndexCond:(str1_str2?|'{10,33}'::text[])
(4rows)
Time:0.688ms


我们想办法来优化这条语句, 如果把这条语句变成跟原始语句一样的话,那么是否就可以用到BTREE索引了?

接下来,建立一个基于BTREE的函数索引,

t_girl=#createindexidx_str1_str2_akeysonstatus_check_hstoreusingbtree(array_to_string(akeys(str1_str2),','));
CREATEINDEX
Time:394.123ms
OK,变化语句来执行下同样的检索,
t_girl=#selectis_yes,svals(str1_str2)fromstatus_check_hstorewherearray_to_string(akeys(str1_str2),')in('10','33');
is_yes|skeys|svals
--------+-------+----------------------
t|10|d3d9446802a44259755d
t|23|37693cfc748049e45d87
f|33|182be0c5cdcd5072bb18
(3rows)
Time:0.727ms


这次和原始查询速度一样快了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐