Как использовать оба индекса GIN в одном запросе - PullRequest
0 голосов
/ 27 мая 2020

Я использую (PostgreSQL) 11.8. И у меня есть марка таблицы с индексом GIN

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

И я создал индекс GIN с gin_trgm_ops:

    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, и это правильное и ожидаемое поведение.

enter image description here

Команда объяснения с моим выбором:

    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;

Но когда я добавил дополнительную таблицу fulltext search по brand, как показано ниже:

    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_index и bn_custom_index?

Упоминания о продукте to_tsquery в анализе выглядят так:

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

Результат: enter image description here

Я думаю, может это потому, что я использую тот же способ с 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 приносит прибыль для этого запрос и как использовать оба индекса в одном запросе?

1 Ответ

0 голосов
/ 28 мая 2020

Уже существует индекс, вероятно, весьма избирательный и эффективный, используемый для products.brand_relation_id. Использование второго индекса поверх этого вряд ли будет очень эффективным в этом сценарии. Механизм для объединения индексов имеет накладные расходы, и, если он не дает вам дополнительной избирательности, он, вероятно, того не стоит.

На сервере test / dev вы бы сбросили индекс, которым он является используя и посмотрите, на что он вместо этого изменится. Возможно, он будет использовать один индекс GIN из каждой таблицы, а затем sh объединит эти два результата по условию соединения.

Ваша цель - ускорить запрос или просто заставить его использовать ваш любимый индекс, даже если он медленнее?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...