代码之家  ›  专栏  ›  技术社区  ›  Bill Karwin

为什么PostgreSQL文本搜索gist索引比gin索引慢得多?

  •  16
  • Bill Karwin  · 技术社区  · 15 年前

    我正在测试PostgreSQL文本搜索功能,使用StackOverflow的9月份数据转储作为示例数据。-)

    幼稚的使用方法 LIKE 与搜索120万行匹配的谓词或POSIX正则表达式大约需要 90-105秒 (在我的MacBook上)进行全表扫描,搜索关键字。

    SELECT * FROM Posts WHERE body LIKE '%postgresql%';
    SELECT * FROM Posts WHERE body ~ 'postgresql';
    

    非索引的即席文本搜索查询需要大约 8分钟 :

    SELECT * FROM Posts WHERE to_tsvector(body) @@ to_tsquery('postgresql'); 
    

    创建GIN索引需要大约 40分钟 :

    ALTER TABLE Posts ADD COLUMN PostText TSVECTOR;
    UPDATE Posts SET PostText = to_tsvector(body);
    CREATE INDEX PostText_GIN ON Posts USING GIN(PostText);
    

    (我意识到,通过将其定义为表达式索引,我也可以一步完成这项工作。)

    之后,由GIN索引辅助的查询运行得更快——这需要大约 40毫秒 :

    SELECT * FROM Posts WHERE PostText @@ 'postgresql'; 
    

    但是,当我创建一个gist索引时,结果是完全不同的。它需要不到 2分钟 要创建索引:

    CREATE INDEX PostText_GIN ON Posts USING GIST(PostText);
    

    然后,使用 @@ 文本搜索运算符Takes 90-100秒 . 因此,gist索引确实可以将未索引的TS查询从8分钟提高到1.5分钟。但这比用全表扫描没有任何改进 喜欢 .在Web编程环境中它是无用的。

    我是否遗漏了一些使用gist索引的关键内容?索引是否需要预先缓存在内存中或其他地方?我使用的是MacPorts的纯PostgreSQL安装,没有任何调整。

    建议使用gist索引的方法是什么?或者每个使用postgresql做ts的人都跳过gist索引,只使用gin索引吗?

    附言:我知道斯芬克斯搜索和露西等替代品。我只是想了解PostgreSQL本身提供的特性。

    3 回复  |  直到 11 年前
        1
  •  6
  •   Jonathan Feinberg    15 年前

    尝试

    CREATE INDEX PostText_GIST ON Posts USING GIST(PostText varchar_pattern_ops);
    

    它创建了一个适合前缀查询的索引。查看PostgreSQL文档 Operator Classes and Operator Families .@@运算符只对术语向量敏感;gist索引(带有varchar_pattern_ops)将在like中提供出色的结果。

        2
  •  6
  •   mattonrails    13 年前

    如果您感兴趣,文档可以很好地概述GIST和GIN索引之间的性能差异: GiST and GIN Index Types .

        3
  •  2
  •   John    11 年前

    顺便说一句:如果你还没有满意地回答这个问题,那就是你所做的部分。

    SELECT * FROM Posts WHERE PostText @@ 'postgresql';

    应该是

    SELECT * FROM Posts WHERE PostText @@ to_tsquery('postgresql');