【问题标题】:Trigram Index ORDER BY optimization三元索引 ORDER BY 优化
【发布时间】:2018-12-19 14:05:23
【问题描述】:

我正在尝试实现搜索功能,经过一番调查(请参阅 this interesting read by Yorick Peterse at GitLab),我决定选择使用 pg_trgm 扩展的三元组方法。

我想返回 10 个最相关的行。

以下是我针对具有 110868 行的表测试的几个查询(在 the doc 之后):

SELECT name, similarity(name, 'search query') AS sml
FROM table
ORDER BY sml DESC, name;
Time: 701.814 ms

SELECT name, similarity(name, 'search query') AS sml
FROM table
WHERE name % 'search query'
ORDER BY sml DESC, name;
Time: 376.692 ms

SELECT name, similarity(name, 'search query') AS sml
FROM table
WHERE name % 'search query'
ORDER BY sml DESC, name LIMIT 10;
Time: 378.921 ms

使用 GiST 索引:

CREATE INDEX trigram_index ON table USING GIST (name gist_trgm_ops);
SELECT name, similarity(name, 'search query') AS sml
FROM table
WHERE name % 'search query'
ORDER BY sml DESC, name LIMIT 10;
Time: 36.877 ms

带有 GIN 索引:

CREATE INDEX trigram_index ON table USING GIN (name gin_trgm_ops);
SELECT name, similarity(name, 'search query') AS sml
FROM table WHERE name % 'search query'
ORDER BY sml DESC, name LIMIT 10;
Time: 18.992 ms

使用解释分析:

 Limit  (cost=632.37..632.39 rows=10 width=25) (actual time=22.202..22.204 rows=10 loops=1)
   ->  Sort  (cost=632.37..632.64 rows=111 width=25) (actual time=22.201..22.201 rows=10 loops=1)
         Sort Key: (similarity((name)::text, 'search query'::text)) DESC, name
         Sort Method: top-N heapsort  Memory: 26kB
         ->  Bitmap Heap Scan on table  (cost=208.86..629.97 rows=111 width=25) (actual time=6.900..22.157 rows=134 loops=1)
               Recheck Cond: ((name)::text % 'search query'::text)
               Rows Removed by Index Recheck: 2274
               Heap Blocks: exact=2257
               ->  Bitmap Index Scan on trigram_index  (cost=0.00..208.83 rows=111 width=0) (actual time=6.532..6.532 rows=2408 loops=1)
                     Index Cond: ((name)::text % 'World of Warcraft'::text)
 Planning time: 0.073 ms
 Execution time: 18.521 ms

使用 GIN 索引可显着提高性能。但是,将结果限制为 10 行似乎没有任何影响。

还有我没有考虑过的改进空间吗?我对可以利用我只需要整个表的一小部分这一事实的建议特别感兴趣。

【问题讨论】:

    标签: postgresql database-indexes postgresql-10 pg-trgm


    【解决方案1】:

    正如the documentation 所说,GIN 索引无助于优化ORDER BY 子句:

    上述查询的一个变体是

    SELECT t, t <-> 'word' AS dist
    FROM test_trgm
    ORDER BY dist LIMIT 10;
    

    这可以通过 GiST 索引非常有效地实现,但不能通过 GIN 索引。当只需要少量最接近的匹配时,它通常会击败第一个公式。

    另一方面,对于较大的表,GIN 索引的性能通常优于 GiST 索引。

    所以我认为你应该同时尝试这两种方法,并在实际大小的测试台上使用速度更快的一种。

    我不认为你可以改进那么多,除非使用更多的 RAM 来缓存数据。

    【讨论】:

    • 在我的例子中(即 110000+ 行),GIN 索引的性能更好,尤其是 WHERE name % 'search query'(执行时间从 350 毫秒下降到 18 毫秒左右)。我设法通过将pg_trgm.similarity_threshold 设置为0.5(默认为0.3)来进一步改进它。执行时间降至 4ms!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-31
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多