Вопрос

Я пытаюсь запустить функцию полнотекстового поиска postgres.

У меня есть две таблицы, одну я создал только для тестирования, и ту, в которой я хочу иметь возможность поиска:

Тестовый стол:

webarchive=# \d test_sites
                            Table "public.test_sites"
   Column    |   Type   |                        Modifiers
-------------+----------+---------------------------------------------------------
 id          | integer  | not null default nextval('test_sites_id_seq'::regclass)
 content     | text     |
 tsv_content | tsvector |
Indexes:
    "test_sites_pkey" PRIMARY KEY, btree (id)
    "idx_test_web_pages_content" gin (tsv_content)
Triggers:
    web_pages_testing_content_change_trigger AFTER INSERT OR UPDATE ON test_sites FOR EACH ROW EXECUTE PROCEDURE web_pages_testing_content_update_func()

"Настоящий" стол:

webarchive=# \d web_pages
                                      Table "public.web_pages"
    Column    |            Type             |                       Modifiers
--------------+-----------------------------+--------------------------------------------------------
 id           | integer                     | not null default nextval('web_pages_id_seq'::regclass)
 state        | dlstate_enum                | not null
 errno        | integer                     |
 url          | text                        | not null
 starturl     | text                        | not null
 netloc       | text                        | not null
 file         | integer                     |
 priority     | integer                     | not null
 distance     | integer                     | not null
 is_text      | boolean                     |
 limit_netloc | boolean                     |
 title        | citext                      |
 mimetype     | text                        |
 type         | itemtype_enum               |
 raw_content  | text                        |
 content      | text                        |
 fetchtime    | timestamp without time zone |
 addtime      | timestamp without time zone |
 tsv_content  | tsvector                    |
Indexes:
    "web_pages_pkey" PRIMARY KEY, btree (id)
    "ix_web_pages_url" UNIQUE, btree (url)
    "idx_web_pages_content" gin (tsv_content)
    "idx_web_pages_title" gin (to_tsvector('english'::regconfig, title::text))
    "ix_web_pages_distance" btree (distance)
    "ix_web_pages_distance_filtered" btree (priority) WHERE state = 'new'::dlstate_enum AND distance < 1000000
    "ix_web_pages_priority" btree (priority)
    "ix_web_pages_type" btree (type)
    "ix_web_pages_url_ops" btree (url text_pattern_ops)
Foreign-key constraints:
    "web_pages_file_fkey" FOREIGN KEY (file) REFERENCES web_files(id)
Triggers:
    web_pages_content_change_trigger AFTER INSERT OR UPDATE ON web_pages FOR EACH ROW EXECUTE PROCEDURE web_pages_content_update_func()

Если отбросить лишние биты, у обоих есть content колонка, и a tsv_content колонна с gin() указывайте на это.Существует триггер, который обновляет tsv_content столбец каждый раз, когда content столбец изменен.

Обратите внимание , что Другое gin индекс работает нормально, и на самом деле у меня изначально был gin (to_tsvector('english'::regconfig, content::text)) также индексируйте столбец содержимого вместо второго столбца, но после ожидания, пока этот индекс несколько раз перестроится в ходе тестирования, я решил использовать отдельный столбец для предварительного сохранения значений tsvector.

Выполнение запроса к тестовой таблице использует индекс, как я и ожидал:

webarchive=# EXPLAIN ANALYZE SELECT
    test_sites.id,
    test_sites.content,
    ts_rank_cd(test_sites.tsv_content, to_tsquery($$testing$$)) AS ts_rank_cd_1
FROM
    test_sites
WHERE
    test_sites.tsv_content @@ to_tsquery($$testing$$);
                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on test_sites  (cost=16.45..114.96 rows=25 width=669) (actual time=0.175..3.720 rows=143 loops=1)
   Recheck Cond: (tsv_content @@ to_tsquery('testing'::text))
   Heap Blocks: exact=117
   ->  Bitmap Index Scan on idx_test_web_pages_content  (cost=0.00..16.44 rows=25 width=0) (actual time=0.109..0.109 rows=143 loops=1)
         Index Cond: (tsv_content @@ to_tsquery('testing'::text))
 Planning time: 0.414 ms
 Execution time: 3.800 ms
(7 rows)

Тем не менее, точно такой же запрос к реальной таблице, похоже, никогда ни к чему не приводит но простое старое последовательное сканирование:

webarchive=# EXPLAIN ANALYZE SELECT
       web_pages.id,
       web_pages.content,
       ts_rank_cd(web_pages.tsv_content, to_tsquery($$testing$$)) AS ts_rank_cd_1
   FROM
       web_pages
   WHERE
       web_pages.tsv_content @@ to_tsquery($$testing$$);
                                                       QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
 Seq Scan on web_pages  (cost=0.00..4406819.80 rows=19751 width=505) (actual time=0.343..142325.954 rows=134949 loops=1)
   Filter: (tsv_content @@ to_tsquery('testing'::text))
   Rows Removed by Filter: 12764373
 Planning time: 0.436 ms
 Execution time: 142341.489 ms
(5 rows)

Я увеличил свою рабочую память до 3 ГБ, чтобы посмотреть, не в этом ли проблема, но это не так.

Кроме того, следует отметить, что это довольно большие таблицы - ~ 150 ГБ текста в 4 млн строк (с 8 млн дополнительных строк, где content/tsv_content является NULL).

Тот Самый test_sites таблица содержит 1/000-ю строку из web_pages, поскольку экспериментировать с этим немного непомерно, когда каждый запрос занимает несколько минут.


Я использую postgresql 9.5 (да, я скомпилировал его сам, я хотел ON CONFLICT).Похоже, для этого пока нет тега.

Я внимательно прочитал открытые вопросы с 9.5, и я не вижу, чтобы это было результатом какого-либо из них.


Только что после полной перестройки индекса проблема все еще существует:

webarchive=# ANALYZE web_pages ;
ANALYZE
webarchive=# EXPLAIN ANALYZE SELECT
    web_pages.id,
    web_pages.content,
    ts_rank_cd(web_pages.tsv_content, to_tsquery($$testing$$)) AS ts_rank_cd_1
FROM
    web_pages
WHERE
    web_pages.tsv_content @@ to_tsquery($$testing$$);
                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on web_pages  (cost=10000000000.00..10005252343.30 rows=25109 width=561) (actual time=7.114..146444.168 rows=134949 loops=1)
   Filter: (tsv_content @@ to_tsquery('testing'::text))
   Rows Removed by Filter: 13137318
 Planning time: 0.521 ms
 Execution time: 146465.188 ms
(5 rows)

Обратите внимание, что я буквально только что ANALYZEed, и seqscan отключен.

Это было полезно?

Решение

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

Затем я побежал VACUUM ANALYZE по всей базе данных, и теперь, очевидно, он заметил, что у меня есть индекс.

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

webarchive=# EXPLAIN ANALYZE SELECT
    web_pages.id,
    web_pages.content
FROM
    web_pages
WHERE
    web_pages.tsv_content @@ to_tsquery($$testing$$);
                                                                 QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on web_pages  (cost=1185.79..93687.30 rows=23941 width=189) (actual time=41.448..152.108 rows=134949 loops=1)
   Recheck Cond: (tsv_content @@ to_tsquery('testing'::text))
   Heap Blocks: exact=105166
   ->  Bitmap Index Scan on idx_web_pages_content  (cost=0.00..1179.81 rows=23941 width=0) (actual time=24.940..24.940 rows=134996 loops=1)
         Index Cond: (tsv_content @@ to_tsquery('testing'::text))
 Planning time: 0.452 ms
 Execution time: 154.942 ms
(7 rows)

Я также воспользовался возможностью, чтобы запустить VACUUM FULL; теперь, когда у меня достаточно места для обработки.У меня был изрядный перепад строк в таблице, поскольку я экспериментировал во время разработки, и я хотел бы попытаться объединить любую фрагментацию файла, которая возникла в результате этого.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top