我们有一个使用 trigrams 索引 (pg_trgm) 的 postgres 列。
索引运行良好,但速度非常慢:最终重新检查误报会消耗 >99% 的整体查询时间(位图索引扫描 0.25 秒;重新检查 30.7 秒)。
在我们的例子中,误报是无关紧要的(罕见+我们不在乎),所以重新检查是没有用的。
有没有办法关闭/禁用重新检查步骤,跳过验证误报?最好的方法是什么?
我们有一个使用 trigrams 索引 (pg_trgm) 的 postgres 列。
索引运行良好,但速度非常慢:最终重新检查误报会消耗 >99% 的整体查询时间(位图索引扫描 0.25 秒;重新检查 30.7 秒)。
在我们的例子中,误报是无关紧要的(罕见+我们不在乎),所以重新检查是没有用的。
有没有办法关闭/禁用重新检查步骤,跳过验证误报?最好的方法是什么?
我以为我已经发布了这个,但显然它从未出现过。如果您已经设置为编译扩展,则关闭重新检查是微不足道的:
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,例如,如果您只计算行数,而不是检索它们。
AFAIK 您无法禁用重新检查步骤,但您可以尝试通过增加work_mem
当前会话中的参数来减少重新检查的次数。