SELECT 对索引列进行 COUNT 次查询

SELECT COUNT query on indexed column

我有一个简单的 table 存储不同 ID 的单词。

CREATE TABLE words (
    id INTEGER,
    word TEXT,
);
CREATE INDEX ON words USING hash (id);
CREATE INDEX ON words USING hash (word);

现在我只想计算给定单词出现的次数。我的实际查询有点不同,涉及其他过滤器。

SELECT COUNT(1) FROM "words"
                    WHERE word = 'car'

我的 table 有十亿行,但这个特定查询的答案大约是 45k。 我希望单词上的索引能让查询变得超快,但它仍然需要 1 分 20 秒才能执行,这看起来很不合理。作为比较,SELECT COUNT(1) FROM "words" 需要 1 分钟 57.

这是 EXPLAIN 的输出:

Aggregate  (cost=48667.00..48667.01 rows=1 width=8)
  ->  Bitmap Heap Scan on words  (cost=398.12..48634.05 rows=13177 width=0)
        Recheck Cond: (word = 'car'::text)
        ->  Bitmap Index Scan on words_word_idx  (cost=0.00..394.83 rows=13177 width=0)
              Index Cond: (word = 'car'::text)

我不明白为什么需要重新检查条件以及为什么这个查询效率不高。

只要索引列涉及使用以下运算符之一的比较,您就可以使用 B-Tree 索引:

<   <=   =   >=   >

我假设您正在使用 = 来计算有多少个单词。所以,B-Tree索引满足你的要求。

参考:https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-BTREE

哈希索引不在索引中存储索引值,仅存储其 32 位哈希和 ctid(指向 table 行的指针)。这意味着它们无法自行解决散列冲突,因此它必须去 table 获取值,然后重新检查它。与 btree 索引相比,这可能涉及很多或额外的 IO,btree 索引确实存储值并且可以支持仅索引扫描。