首页 文章

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

提问于
浏览
1

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

查询:

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索引没有多大意义,因为列非常大而且不需要几何运算符(我可能错了) .

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

1 回答

  • 3

    这在很大程度上取决于您的具体用例,这一点并不完全清楚 . 在示例查询中,您正在测试键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索引不是多用途的 . 如果您查看the docs for the hstore module,则'll see which operators are supported by either a gist or gin index on a hstore column*. One of those is 1734485 , which tests if a key is present. Depending on the sparsity of your lookup keys (x, y, z), you might have some luck by defining a gist or gin index on the column and adding an extra condition like 1734486 ; assuming not many rows have the key x this should give you a decent boost, otherwise if the key x is in nearly every row you'将返回全表扫描 .

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

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

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

相关问题