1

我们有一个使用 trigrams 索引 (pg_trgm) 的 postgres 列。

索引运行良好,但速度非常慢:最终重新检查误报会消耗 >99% 的整体查询时间(位图索引扫描 0.25 秒;重新检查 30.7 秒)。

在我们的例子中,误报是无关紧要的(罕见+我们不在乎),所以重新检查是没有用的。

有没有办法关闭/禁用重新检查步骤,跳过验证误报?最好的方法是什么?

4

2 回答 2

3

我以为我已经发布了这个,但显然它从未出现过。如果您已经设置为编译扩展,则关闭重新检查是微不足道的:

diff --git a/contrib/pg_trgm/trgm_gin.c b/contrib/pg_trgm/trgm_gin.c
index 4dbf0ffb68..a23855cad5 100644
--- a/contrib/pg_trgm/trgm_gin.c
+++ b/contrib/pg_trgm/trgm_gin.c
@@ -307,7 +307,7 @@ gin_trgm_triconsistent(PG_FUNCTION_ARGS)
            /* FALL THRU */
        case LikeStrategyNumber:
            /* Check if all extracted trigrams are presented. */
-           res = GIN_MAYBE;
+           res = GIN_TRUE;
            for (i = 0; i < nkeys; i++)
            {
                if (check[i] == GIN_FALSE)

当然,这会给你错误的答案,你似乎可以接受。然而,您现在或未来的同事可能会对此感到惊讶,特别是如果他们在从当前上下文中删除的某些上下文中使用 pg_trgm。所以它应该在某个地方清楚地记录下来。您可以将 pg_trgm 派生到一个新的扩展中并在那里进行更改,但这需要对函数和运算符进行相当繁琐的重命名,以免它们发生冲突。也许更好的选择是创建一个新版本的 pg_trgm,它有一个额外的操作符来实现这个不重新检查功能,让 ~~(LIKE 是它的别名)去做它目前所做的事情。不过,这仍然会带来升级危险。

另外,我怀疑它实际上会使事情变得更快。可能时间实际上是花在桌子上的 IO 上,而不是重新检查上。您可以通过打开track_io_timing并执行来检查这一点EXPLAIN (ANALYZE, BUFFERS)。在某些情况下,跳过重新检查也可能会跳过 IO,例如,如果您只计算行数,而不是检索它们。

于 2020-05-08T13:26:18.043 回答
1

AFAIK 您无法禁用重新检查步骤,但您可以尝试通过增加work_mem当前会话中的参数来减少重新检查的次数。

于 2020-05-05T18:46:36.547 回答