PostgreSQL hstore:使用索引提高LIKE性能?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL hstore:使用索引提高LIKE性能?相关的知识,希望对你有一定的参考价值。

我有一大组具有不均匀属性的非规范化数据(有些属性存在,有些属性不存在)并将其插入单个列。此列包含大约300个键/值对,每行总大小为5000个字符。我想用ilikeOR运算符对其中一些属性进行字符串搜索查询,共计100000行。

查询:

SELECT hstore->'a' AS a, hstore->'b' AS b,hstore->'c' AS c
  FROM table
  WHERE
       hstore->'x' ILIKE '123%' 
    or hstore->'y' ILIKE '123%'
    or hstore->'z' ILIKE '123%'

在unindexed表上使用此查询,我得到> 500ms运行时(explain analyze)。

使用我的旧RDBMS索引表,其中每个属性都在一个列中,我实现了更好的性能,但不太灵活。

我在那些hstore属性上尝试了不同的/多个索引,比如

CREATE INDEX idx_table_hstore ON table( (hstore->'a') )

每个都有一个索引,但性能与没有索引相同。

据我所知,GIN / GIST索引没有多大意义,因为列非常大而且不需要几何运算符(我可能错了)。

在这种情况下,您使用什么索引方法来实现与使用经典模型相似甚至更好的性能?

答案

这在很大程度上取决于您的具体用例,这一点并不完全清楚。在示例查询中,您正在测试键x,y和z的值。如果这三个键(或所有键的一些相对较小的子集)是唯一用于查找的键,您可以考虑将它们移动到它们自己的列 - 然后您的查找字段是固定的,但您仍然具有hstore列的灵活性。

您是否已在每个单独的键或仅查找列上创建索引也不清楚。如果你在每个键上做了其中一个,你在谈论大约300个索引(你提到有大约300个键),然后你也放弃了hstore的一些灵活性(通过创建其中一个索引)每一把钥匙)。我会在这里只查看查找列(x,y,z)并稍微调整它们,如下所示:

create index idx_t_h_x on t ((lower(h->'x')));

您提到的索引不支持ilike运算符,因此您需要在值的较低(或较高)上进行索引,然后修改谓词以匹配,如下所示:

SELECT hstore->'a' AS a, hstore->'b' AS b,hstore->'c' AS c
FROM table
WHERE lower(hstore->'x') LIKE '123%'

此外,gin / gist索引不仅适用于几何操作(实际上两个名称中的“g”都是“一般化的” - 它们的目的是多用途)。如果你查看the docs for the hstore module,你会看到hstore列上的gist或gin索引支持哪些运算符*。其中一个是“?”,它测试是否存在密钥。根据查找键(x,y,z)的稀疏性,您可以通过在列上定义gist或gin索引并添加额外条件(例如“where(hstore?'x'和hstore->')来获得一些运气。 x'ilike'123%')“;假设没有很多行有密钥x这应该给你一个不错的提升,否则如果密钥x几乎在每一行,你将回到全表扫描。

在决定是否使用gist或gin时,如果你查看postgres文档,那么你可以找到一些指导原则,基本上杜松子酒往往更快查找但占用更多空间并且构建和维护速度较慢(意思是记住你是在写更多还是读更多数据) - 我不确定是否有针对hstore类型的具体建议。

哦,显然这一切都假设您的服务器已根据您的硬件和使用情况进行了适当配置。正如我所指出的,您提供的索引不支持ilike运算符,因此永远不会使用。一旦获得了您认为应该使用的索引,您可以尝试禁用表扫描(检查config for enable_seqscan)以查看您是否可以找出计划程序未使用它的原因。如果你的配置是开箱即用的,你可能将random_page_cost设置为高,如果你的work_mem不够高,你可能会在磁盘排序上做很多事情,等等。

*只是在这里指出一个主题,并非所有索引类型都支持所有运算符。

以上是关于PostgreSQL hstore:使用索引提高LIKE性能?的主要内容,如果未能解决你的问题,请参考以下文章

通过 SQLAlchemy 到 PostgreSQL HSTORE 的 Python 列表

Postgresql:如何在不使用中间 hstore 的情况下将键值表转换为 json

sql 在postgresql中使用动态列名创建交叉表/数据透视表形式的hstore字段

PostgreSQL 9.2 - 将 TEXT json 字符串转换为 json/hstore 类型

获取空 hstore 的记录

如何在 Postgres 中的 JSON 字段上创建索引?