【问题标题】:How to use both GIN index in one query如何在一个查询中同时使用两个 GIN 索引
【发布时间】:2020-05-27 13:03:36
【问题描述】:

我使用 (PostgreSQL) 11.8。我有带有 GIN 索引的表品牌

      CREATE INDEX bn_custom_index ON brand
      USING GIN(to_tsvector('pg_catalog.swedish', brand_name));

我用gin_trgm_ops创建了GIN索引:

    CREATE EXTENSION IF NOT EXISTS pg_trgm;
    CREATE INDEX brand_trgm_idx ON brand USING GIN (brand_name gin_trgm_ops);

以及带有GIN索引的表产品:

    CREATE INDEX npd_swedish_custom_index ON products
    USING GIN(to_tsvector('pg_catalog.swedish', name||price||description))

然后,在查询中我将fulltext search 仅用于产品表。

在分析部分我发现了npd_swedish_custom_index 索引,这是正确的预期行为。

带有我的选择的解释命令:

    EXPLAIN ANALYZE
    SELECT
            DISTINCT brand_alias.id,
            brand_alias.brand_name AS "brandName",
            brand_alias.created_at AS "createdAt"
    FROM brand brand_alias
    INNER JOIN products products_alias ON products_alias.brand_relation_id = brand_alias.id

            JOIN to_tsquery('pg_catalog.swedish', 'ball:*') query_search
            ON to_tsvector('pg_catalog.swedish', products_alias.name||products_alias.price||products_alias.description) @@ query_search  
            GROUP BY brand_alias.id
     ORDER BY "createdAt" DESC                                          
            LIMIT 10
            OFFSET 0;

但是当我通过brand 表添加额外的fulltext search 时,如下所示:

    EXPLAIN ANALYZE 
    SELECT
            DISTINCT brand_alias.id,
            brand_alias.brand_name AS "brandName",
            brand_alias.created_at AS "createdAt"
    FROM brand brand_alias
    INNER JOIN products products_alias ON products_alias.brand_relation_id = brand_alias.id

            JOIN to_tsquery('pg_catalog.swedish', 'ball:*') query_search
            ON to_tsvector('pg_catalog.swedish', products_alias.name||products_alias.price||products_alias.description) @@ query_search  
        JOIN to_tsquery('pg_catalog.swedish', 'Louis:*') query_search_facet
        ON to_tsvector('pg_catalog.swedish',brand_alias.brand_name) @@ query_search_facet
            GROUP BY brand_alias.id
     ORDER BY "createdAt" DESC                                          
                    LIMIT 10
                    OFFSET 0;

我没有在使用npd_swedish_custom_index 的分析部分找到,但找到了bn_custom_index。为什么npd_swedish_custom_indexbn_custom_index inidex 没有同时用于此查询?

在分析中提及产品to_tsquery 看起来像:

     Join Filter: (to_tsvector('swedish'::regconfig, (((products_alias.name)::text || (products_alias.price)::text) || products_alias.description)) @@ query_search.query_search)

结果是:

我想这可能是因为我使用与JOIN to_tsquery 相同的方式并尝试使用pg_trgm 方式。

    CREATE EXTENSION IF NOT EXISTS pg_trgm; 
    CREATE INDEX brand_trgm_idx ON brand USING GIN (brand_name gin_trgm_ops);

然后,我尝试了这种方法:

    EXPLAIN ANALYZE
    SELECT
            DISTINCT brand_alias.id,
            brand_alias.brand_name AS "brandName",
            brand_alias.created_at AS "createdAt"
    FROM brand brand_alias
    INNER JOIN products products_alias ON products_alias.brand_relation_id = brand_alias.id

            JOIN to_tsquery('pg_catalog.swedish', 'ball:*') query_search
            ON to_tsvector('pg_catalog.swedish', products_alias.name||products_alias.price||products_alias.description) @@ query_search  
            WHERE brand_alias.brand_name % 'Louis'
            GROUP BY brand_alias.id
     ORDER BY "createdAt" DESC                                          
                    LIMIT 10
                    OFFSET 0;

但是,在这种情况下,我仍然没有找到npd_swedish_custom_index

我想知道在这种情况下,我的产品表 npd_swedish_custom_index 中的索引为此查询获利,以及如何在一个查询中使用这两个索引?

【问题讨论】:

  • 您应该将文本发布为文本,而不是图像。尤其是那些有用信息在图像边缘被截断的图像。

标签: postgresql


【解决方案1】:

products.brand_relation_id 上已经有一个索引,可能是一个高度选择性和高效的索引。在这种情况下,在该索引之上使用第二个索引不太可能非常有效。组合索引的机制有开销,如果它不能为您带来很多额外的选择性,那可能就不值得了。

在测试/开发服务器上,您可以删除它当前使用的索引,然后查看它更改为什么。也许它会使用每个表中的一个 GIN 索引,然后在连接条件上对这两个结果进行哈希连接。

您的目标是让查询更快,还是只是强制它使用您最喜欢的索引,即使这很慢?

【讨论】:

  • 我的目标是让查询更快
猜你喜欢
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 1970-01-01
相关资源
最近更新 更多