Postgres 相似度函数没有适当地使用 trigram 索引
Postgres similarity function not appropriately using trigram index
我有一个简单的 person
table 和一个 last_name
列,我添加了一个 GIST 索引
CREATE INDEX last_name_idx ON person USING gist (last_name gist_trgm_ops);
根据 https://www.postgresql.org/docs/10/pgtrgm.html 上的文档,<->
运算符应使用此索引。但是,当我实际尝试使用此查询使用此差异运算符时:
explain verbose select * from person where last_name <-> 'foobar' > 0.5;
我回来了:
Seq Scan on public.person (cost=0.00..290.82 rows=4485 width=233)
Output: person_id, first_name, last_name
Filter: ((person.last_name <-> 'foobar'::text) < '0.5'::double precision)
而且索引似乎没有被使用。但是,如果我将 %
运算符与此命令一起使用:
explain verbose select * from person where last_name % 'foobar';
好像使用了索引:
Bitmap Heap Scan on public.person (cost=4.25..41.51 rows=13 width=233)
Output: person_id, first_name, last_name
Recheck Cond: (person.last_name % 'foobar'::text)
-> Bitmap Index Scan on last_name_idx (cost=0.00..4.25 rows=13 width=0)
Index Cond: (person.last_name % 'foobar'::text)
我还注意到,如果我将运算符移动到查询的 select 部分,索引将再次被忽略:
explain verbose select last_name % 'foobar' from person;
Seq Scan on public.person (cost=0.00..257.19 rows=13455 width=1)
Output: (last_name % 'foobar'::text)
关于相似度函数如何使用三元组索引,我是否遗漏了一些明显的信息?
我在 OSX.
上使用 Postgres 10.5
编辑 1
根据 Laurenz 的建议,我尝试设置 enable_seqscan = off
但不幸的是,使用 <->
运算符的查询似乎仍然忽略了索引。
show enable_seqscan;
enable_seqscan
----------------
off
explain verbose select * from person where last_name <-> 'foobar' < 0.5;
-----------------------------------------------------------------------------------------------------------------------------
Seq Scan on public.person (cost=10000000000.00..10000000290.83 rows=4485 width=233)
Output: person_id, first_name, last_name
Filter: ((person.last_name <-> 'foobar'::text) < '0.5'::double precision)
这种行为对于所有类型的索引都是正常的。
第一个查询不是可以使用索引的表单。为此,条件必须采用
形式
<indexed expression> <operator supported by the index> <quasi-constant>
其中最后一个表达式在索引扫描期间保持不变,运算符 returns 是一个布尔值。您的表达式 ´last_name <-> 'foobar' > 0.5` 不是那种形式。
必须在 ORDER BY
子句中使用 <->
运算符才能使用索引。
第三个查询不使用索引,因为该查询影响 table 的 所有 行。索引不会加快表达式的计算速度,它仅对快速识别 table 的子集(或按特定排序顺序获取行)有用。
我有一个简单的 person
table 和一个 last_name
列,我添加了一个 GIST 索引
CREATE INDEX last_name_idx ON person USING gist (last_name gist_trgm_ops);
根据 https://www.postgresql.org/docs/10/pgtrgm.html 上的文档,<->
运算符应使用此索引。但是,当我实际尝试使用此查询使用此差异运算符时:
explain verbose select * from person where last_name <-> 'foobar' > 0.5;
我回来了:
Seq Scan on public.person (cost=0.00..290.82 rows=4485 width=233)
Output: person_id, first_name, last_name
Filter: ((person.last_name <-> 'foobar'::text) < '0.5'::double precision)
而且索引似乎没有被使用。但是,如果我将 %
运算符与此命令一起使用:
explain verbose select * from person where last_name % 'foobar';
好像使用了索引:
Bitmap Heap Scan on public.person (cost=4.25..41.51 rows=13 width=233)
Output: person_id, first_name, last_name
Recheck Cond: (person.last_name % 'foobar'::text)
-> Bitmap Index Scan on last_name_idx (cost=0.00..4.25 rows=13 width=0)
Index Cond: (person.last_name % 'foobar'::text)
我还注意到,如果我将运算符移动到查询的 select 部分,索引将再次被忽略:
explain verbose select last_name % 'foobar' from person;
Seq Scan on public.person (cost=0.00..257.19 rows=13455 width=1)
Output: (last_name % 'foobar'::text)
关于相似度函数如何使用三元组索引,我是否遗漏了一些明显的信息?
我在 OSX.
上使用 Postgres 10.5编辑 1
根据 Laurenz 的建议,我尝试设置 enable_seqscan = off
但不幸的是,使用 <->
运算符的查询似乎仍然忽略了索引。
show enable_seqscan;
enable_seqscan
----------------
off
explain verbose select * from person where last_name <-> 'foobar' < 0.5;
-----------------------------------------------------------------------------------------------------------------------------
Seq Scan on public.person (cost=10000000000.00..10000000290.83 rows=4485 width=233)
Output: person_id, first_name, last_name
Filter: ((person.last_name <-> 'foobar'::text) < '0.5'::double precision)
这种行为对于所有类型的索引都是正常的。
第一个查询不是可以使用索引的表单。为此,条件必须采用
形式<indexed expression> <operator supported by the index> <quasi-constant>
其中最后一个表达式在索引扫描期间保持不变,运算符 returns 是一个布尔值。您的表达式 ´last_name <-> 'foobar' > 0.5` 不是那种形式。
必须在 ORDER BY
子句中使用 <->
运算符才能使用索引。
第三个查询不使用索引,因为该查询影响 table 的 所有 行。索引不会加快表达式的计算速度,它仅对快速识别 table 的子集(或按特定排序顺序获取行)有用。