【问题标题】:Postgres similarity function not appropriately using trigram indexPostgres 相似度函数不恰当地使用三元组索引
【发布时间】:2018-11-13 16:32:11
【问题描述】:

我有一个简单的 person 表,其中包含一个 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)

我还注意到,如果我将运算符移动到查询的选择部分,索引会再次被忽略:

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,但不幸的是,使用 &lt;-&gt; 运算符的查询似乎仍然忽略了索引。

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)

【问题讨论】:

    标签: postgresql similarity postgresql-10 trigram


    【解决方案1】:

    这种行为对于所有类型的索引都是正常的。

    第一个查询不是可以使用索引的形式。为此,条件必须是以下形式

    <indexed expression> <operator supported by the index> <quasi-constant>
    

    其中最后一个表达式在索引扫描期间保持不变,并且运算符返回一个布尔值。你的表达 ´last_name 'foobar' > 0.5` 不是那种形式。

    &lt;-&gt; 运算符必须在 ORDER BY 子句中使用才能使用索引。

    第三个查询不使用索引,因为该查询会影响表的所有行。索引不会加快表达式的计算速度,它只有助于快速识别表的子集(或按特定排序顺序获取行)。

    【讨论】:

    • 谢谢,这一切都说得通。但是,我只是尝试设置enable_seqscan = off,但查询仍在使用&lt;-&gt; 运算符进行seq 扫描。
    • 我已根据您的建议结果更新了问题。
    猜你喜欢
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    相关资源
    最近更新 更多