2

У меня возникают проблемы, при которых postgres используют мои индексы с несколькими столбцами для полного поиска с использованием расширения btree_gin. Это для страницы поиска статей. Идея использования btree_gin, чтобы иметь возможность получить поле «ID» для сортировки и magazine_id в качестве фильтра:Postgresql не использует многоколоночные индексы (btree_gin)

CREATE INDEX idx_gin_search ON article USING gin(id, magazine_id, search_vector_full) WITH (fastupdate = off); 

Postgres решает использовать индекс ВТКЕЯ на журнале вместо, а затем фильтр (= медленно) :

Executed SQL 
SELECT ••• FROM article WHERE (((article.search_vector) @@  
(plainto_tsquery('pg_catalog.english', 'interesting'))) AND  
article.magazine_id = 7) ORDER BY article.id ASC LIMIT 36 
Time 13.4780406952 ms 

QUERY PLAN 
Limit (cost=2021.87..2021.96 rows=36 width=384) (actual time=9.782..9.787 rows=36 loops=1) 
    -> Sort (cost=2021.87..2027.49 rows=2248 width=384) (actual time=9.781..9.784 rows=36 loops=1) 
    Sort Key: id 
    Sort Method: top-N heapsort Memory: 53kB 
    -> Index Scan using idx_magazine_id on article (cost=0.29..1952.53 rows=2248 width=384) (actual time=0.035..8.924 rows=2249 loops=1) 
      Index Cond: (magazine_id = 7) 
      Filter: (search_vector @@ '''interesting'''::tsquery) 
      Rows Removed by Filter: 11413 
Planning time: 4.600 ms 
Execution time: 9.860 ms 

Затем, что я нахожу даже понять менее, является то, что он также отказывается использовать этот простой индекс ВТКЕЯ на странице LIST для статей, где они вышеперечисленные й на страницу в порядке убывания:

CREATE INDEX idx_btree_listing ON article USING btree(id DESC, magazine_id); 

Опять он не использует индекс в нескольких столбцов:

Executed SQL 
SELECT ••• FROM article WHERE article.magazine_id = 7 
ORDER BY article.id DESC LIMIT 36 
Time 1.4750957489 ms 

QUERY PLAN 
Limit (cost=0.29..7.48 rows=36 width=384) (actual time=0.034..0.115 rows=36 loops=1) 
-> Index Scan Backward using idx_magazine_id on article (cost=0.29..2729.56 rows=13662 width=384) (actual time=0.031..0.107 rows=36 loops=1) 
    Filter: (magazine_id = 7) 
    Planning time: 1.354 ms 
    Execution time: 0.207 ms 

EDIT: Выше подстроено разработка с меньшим количеством записей и только один журнал, следовательно, быстрая скорость. Вот бревно производится auto_explain на сервере:

duration: 230.629 ms plan: 
SELECT article.id, article.title, article.date, article.content FROM article WHERE article.magazine_id = 7 ORDER BY article.id DESC LIMIT 36 

Limit (cost=0.42..43.67 rows=36 width=306) (actual time=229.876..229.995 rows=36 loops=1) 
    -> Index Scan Backward using idx_magazine_id on article (cost=0.42..239539.22 rows=199379 width=306) (actual time=229.866..229.968 rows=36 loops=1) 
    Filter: (article.magazine_id = 7) 
    Rows Removed by Filter: 116414 

Я был бы признателен кто-то может дать мне советы для моей дальнейшей отладки на этом.

+1

Почему второе заявление использует b-дерево, если результат может быть полностью восстановлен с использованием индекса 'mmxxx_sitevideo_pkey' - с временем выполнения 0,2 миллисекунды это кажется мне достаточно быстрым. Время планирования заняло больше времени, но общая продолжительность работы по-прежнему составляет всего 1,5 ** млн. ** секунд. Какую производительность вы ожидаете? Как быстро вам это нужно? Хотя я должен признать, что время планирования (особенно первое) кажется довольно высоким для таких простых утверждений. –

+0

Да, что вы говорите, имеет абсолютный смысл, однако я должен уточнить, что это из установки разработки с гораздо меньшими данными, чем производственный сервер. На рабочем сервере я использую модуль auto_explain и получаю тот же план выполнения. В моей БД разработки у меня есть только один журнал_ид, на реальном сервере я получаю тот же запрос, а затем это занимает больше времени, извините, что я должен был добавить производственный запрос, теперь добавили его в исходное сообщение. (Также забыл переименовать этот индекс, который вы указываете idx_magazine_id для «упрощения» ;-)) – tdma

+0

Затем отправьте план выполнения (используя 'объяснять (анализировать, подробно)' из производства. –

ответ

1

Первый столбец в вашем индексе с несколькими столбцами - id. Вы не фильтруете идентификатор, поэтому postgres не будут использовать этот индекс. Вам не нужно фильтровать все столбцы в индексе, но столбцы, на которых вы выполняете фильтрацию, должны быть первыми n столбцами в индексе.

Попробуйте поэкспериментировать с вариациями индекса, который у вас есть, например, с перемещением id до конца или с пропуском id из индекса.

+0

Привет, спасибо за ваши отзывы. Я попытался изменить порядок полей индекса, а также без поля id, как вы предлагаете, но план выполнения то же самое и остается намного выше 100 мс ... Я думаю, что операция сортировки является проблемой.Знаете ли вы, что если этот запрос (я имею в виду второй в моем первоначальном вопросе), будет ли überhaubt поддерживать все из индекса? – tdma

+0

ОК. Проблема с запросом 2 разрешена. Order_by сбивал с толку планировщика. Я пробовал все, чтобы он работал с запросом, как это было, включая изменение default_statistics_target и других параметров планировщика. Он продолжал делать неправильный выбор (снова поднимает мысль о том, должны ли postgres иметь индексные подсказки). В итоге я создал новый столбец id_sort с идентичным содержимым как id и индекс btree (journal_id, id_sort desc), который хорошо используется и работает в течение нескольких мс. Это довольно абсурдно. – tdma