在 postgres 中创建不区分大小写的 trigram-index 的正确方法是什么?
What is the correct way to create a case-insensitive trigram-index in postgres?
...这是我应该做的事吗?
根据我的简短测试,制作三元组索引并使用
进行搜索
where name like '%query%'
比
快
where name ilike '%query%'
看来我应该这样做,但令我惊讶的是我一直没能找到方法。
(我的测试数据相当均匀 - 150 万行由重复的 16 个条目组成。我可以想象这可能会影响结果。)
这是我预期的工作方式(注意 lower(name)
):
create extension pg_trgm;
create table users(name text);
insert into users values('Barry');
create index "idx" on users using gin (lower(name) gin_trgm_ops);
select count(*) from users where (name like '%bar%');
但是这个returns0
.
select count(*) from users where (name like '%Bar%');
或
select count(*) from users where (name ilike '%bar%');
工作,这让我相信索引中的三字母不是 lower()
'。我是否误解了它的工作原理?那里不能调用lower
吗?
我注意到这个
select show_trgm('Barry')
returns小写八卦:
{" b"," ba",arr,bar,rry,"ry "}
所以我很困惑。
八卦肯定是小写的。
当您考虑如何使用三元组索引时,这个难题就迎刃而解了:它们充当过滤器,消除了大多数 non-matches,但允许误报结果(其中一个原因是它们不区分大小写)。这就是为什么总是需要重新检查以消除这些误报,这也是为什么您总是进行位图索引扫描的原因。
ILIKE
查询可能会比较慢,因为它有更多的结果,或者因为不区分大小写的比较需要更多的努力。
...这是我应该做的事吗?
根据我的简短测试,制作三元组索引并使用
进行搜索where name like '%query%'
比
快where name ilike '%query%'
看来我应该这样做,但令我惊讶的是我一直没能找到方法。
(我的测试数据相当均匀 - 150 万行由重复的 16 个条目组成。我可以想象这可能会影响结果。)
这是我预期的工作方式(注意 lower(name)
):
create extension pg_trgm;
create table users(name text);
insert into users values('Barry');
create index "idx" on users using gin (lower(name) gin_trgm_ops);
select count(*) from users where (name like '%bar%');
但是这个returns0
.
select count(*) from users where (name like '%Bar%');
或
select count(*) from users where (name ilike '%bar%');
工作,这让我相信索引中的三字母不是 lower()
'。我是否误解了它的工作原理?那里不能调用lower
吗?
我注意到这个
select show_trgm('Barry')
returns小写八卦:
{" b"," ba",arr,bar,rry,"ry "}
所以我很困惑。
八卦肯定是小写的。
当您考虑如何使用三元组索引时,这个难题就迎刃而解了:它们充当过滤器,消除了大多数 non-matches,但允许误报结果(其中一个原因是它们不区分大小写)。这就是为什么总是需要重新检查以消除这些误报,这也是为什么您总是进行位图索引扫描的原因。
ILIKE
查询可能会比较慢,因为它有更多的结果,或者因为不区分大小写的比较需要更多的努力。