Frage

Ich versuche, die Postgres-Volltextsuchfunktion funktionsfähig zu machen.

Ich habe zwei Tabellen, eine habe ich nur zum Testen erstellt und die eigentliche Tabelle möchte ich durchsuchen können:

Testtabelle:

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()

„Echte“ Tabelle:

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()

Abgesehen von den zusätzlichen Bits haben beide eine content Spalte und a tsv_content Spalte mit a gin() Index darauf.Es gibt einen Auslöser, der die aktualisiert tsv_content Spalte jedes Mal, wenn die content Spalte wird geändert.

Notiere dass der andere gin Index funktioniert gut, und ich hatte ursprünglich tatsächlich einen gin (to_tsvector('english'::regconfig, content::text)) Index auch für die Inhaltsspalte anstelle der zweiten Spalte, aber nachdem ich beim Testen einige Male darauf gewartet hatte, dass dieser Index neu erstellt wurde, entschied ich mich, eine separate Spalte zu verwenden, um die tsvector-Werte vorab zu speichern.

Beim Ausführen einer Abfrage für die Testtabelle wird der Index wie erwartet verwendet:

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)

Allerdings ist die genau das gleiche Eine Abfrage der realen Tabelle scheint nie zu irgendetwas zu führen Aber ein einfacher alter sequenzieller Scan:

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)

Ich habe meinen Arbeitsspeicher auf 3 GB erhöht, um zu sehen, ob das das Problem war, aber das ist nicht der Fall.

Darüber hinaus ist zu beachten, dass es sich um ziemlich große Tabellen handelt – etwa 150 GB Text in 4 Millionen Zeilen (mit 8 Millionen zusätzlichen Zeilen). content/tsv_content Ist NULL).

Der test_sites Die Tabelle enthält 1/1000 der Zeilen web_pages, da es etwas unerschwinglich ist, damit zu experimentieren, wenn jede Abfrage mehrere Minuten dauert.


Ich verwende Postgresql 9.5 (ja, ich habe es selbst kompiliert, ich wollte ON CONFLICT).Dafür scheint es noch kein Tag zu geben.

Ich habe das durchgelesen offene Punkte mit 9,5, und ich kann mir nicht vorstellen, dass dies auf irgendeinen von ihnen zurückzuführen ist.


Nach einer kompletten Neuerstellung des Index besteht das Problem immer noch:

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)

Beachten Sie, dass ich buchstäblich nur ANALYZEed und seqscan ist deaktiviert.

War es hilfreich?

Lösung

Nun, ich habe etwas Zeit damit verbracht, auf der Festplatte mit der Datenbank etwas zusätzlichen Speicherplatz zu schaffen und einige andere Datenbanken auf eine andere SSD zu verschieben.

Ich bin dann gerannt VACUUM ANALYZE in der gesamten Datenbank, und jetzt ist mir offenbar aufgefallen, dass ich den Index habe.

Ich hatte zuvor sowohl analysiert als auch gesaugt nur dieser Tisch, aber anscheinend machte es irgendwie einen Unterschied, es allgemein und nicht nur für eine bestimmte Tabelle zu tun.Stelle dir das vor.

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)

Ich nutzte auch die Gelegenheit, eine zu leiten VACUUM FULL; Jetzt habe ich genug Platz für die Bearbeitung.Da ich während der Entwicklung experimentiert habe, ist in der Tabelle ziemlich viel Zeilenwechsel aufgetreten, und ich möchte versuchen, die daraus resultierende Dateifragmentierung zu konsolidieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top