使用三元组索引不一致的查询执行时间?

Jor*_*eno 5 postgresql

我有一张桌子residences...

我安装了trgm: create extension pg_trgm;

使用以下方法将三元组索引添加到grpname列后:

CREATE INDEX residences_name_trgm ON residences USING GIN (name gin_trgm_ops);
CREATE INDEX residences_grp_trgm ON residences USING GIN (grp gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)

并检查一个简单查询的性能......似乎name列上查询的总运行时间运行速度提高了大约 100 倍。为什么是这样?

EXPLAIN ANALYZE SELECT * FROM residences WHERE name ILIKE '%Sutton%';
                                                            QUERY PLAN                                                            
----------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on residences  (cost=36.02..47.90 rows=3 width=1872) (actual time=0.390..0.720 rows=21 loops=1)
   Recheck Cond: ((name)::text ~~ '%Sutton%'::text)
   ->  Bitmap Index Scan on residences_name_trgm_gin  (cost=0.00..36.02 rows=3 width=0) (actual time=0.354..0.354 rows=21 loops=1)
         Index Cond: ((name)::text ~~ '%Sutton%'::text)
 Total runtime: 0.814 ms
(5 rows)
Run Code Online (Sandbox Code Playgroud)

EXPLAIN ANALYZE SELECT * FROM residences WHERE grp ILIKE '%Sutton%';
                                                                  QUERY PLAN                                                                   
-----------------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on residences  (cost=97.93..8879.41 rows=5927 width=1872) (actual time=5.516..115.634 rows=5968 loops=1)
   Recheck Cond: ((grp)::text ~~ '%Sutton%'::text)
   ->  Bitmap Index Scan on residences_grp_trgm_gin  (cost=0.00..96.45 rows=5927 width=0) (actual time=4.366..4.366 rows=5968 loops=1)
         Index Cond: ((grp)::text ~~ '%Sutton%'::text)
 Total runtime: 119.779 ms
(5 rows)
Run Code Online (Sandbox Code Playgroud)

作为参考,namegrp列都是CHARACTER VARYING(50)

此外......计算每列中的不同值会产生:

SELECT COUNT(DISTINCT grp) FROM residences;
421

SELECT COUNT(DISTINCT name) FROM residences
7750
Run Code Online (Sandbox Code Playgroud)

也就是说,该name列实际上有大约 20 倍的不同值,但返回值的速度要快得多。

有关此技术的更多信息可以在 depesz 的文章WAITING FOR 9.1 – FASTER LIKE/ILIKE以及PalominoDB 博客上的另一个类似教程中找到。

Cra*_*ger 5

也就是说, name 列实际上有大约 20 倍的不同值,但返回值的速度要快得多。

正是如此。上的索引name更具选择性比的指标grp,因此索引的使用是更有效的。

这是事实,你的第一个查询,在确认name现场,位图索引扫描,residences_grp_trgm_gin只得到21结果如图actual( ... rows=21 ...)中的explain analyze输出。在grp你得到5968个结果。

在位图索引扫描中,每次堆读取和重新检查都有很大的成本,因此找到 21 行比找到 5968 行要快得多是完全合理的。

顺便说一句,请始终显示select version()您的服务器配置,以及与 wiki 报告问题指南相关的任何其他内容。