Pregunta

Estoy tratando de conseguir el postgres texto completo-facilidad de búsqueda funcional.

Tengo dos tablas, una que he creado sólo para pruebas, y el real de la que quiero ser capaz de buscar:

Tabla De Prueba:

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

Tabla "Real":

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

Bits adicionales a un lado, ambos tienen un content columna, y un tsv_content columna con un gin() índice en ella.Hay un desencadenador que se actualiza el tsv_content columna cada vez que el content la columna se modifica.

Tenga en cuenta que el otros gin índice funciona bien, y yo en realidad tenía inicialmente un gin (to_tsvector('english'::regconfig, content::text)) el índice sobre el contenido de la columna así, en lugar de la segunda columna, pero después de esperar para que el índice de reconstruir un par de veces en la prueba, he decidido utilizar una columna separada para pre-almacén de la tsvector valores.

La ejecución de una consulta en la tabla de prueba utiliza el índice como yo esperaba:

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)

Sin embargo, la exactamente el mismo consulta sobre la mesa real nunca parece resultar en nada pero un viejo y simple examen secuencial:

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)

He aumentado mi trabajo de memoria de 3 GB para ver si ese era el problema, y no lo es.

Además, cabe señalar que estos son bastante grandes tablas - ~150GB de texto a través de 4M filas (con 8 m filas adicionales donde content/tsv_content es NULL).

El test_sites la tabla tiene 1/1000 de las filas de web_pages, como es un poco prohibitivo para experimentar con cuando cada consulta tarda varios minutos.


Estoy usando postgresql 9.5 (sí, he compilado yo mismo, yo quería ON CONFLICT).No parece ser una etiqueta para los que todavía.

He leído a través de la temas abiertos con 9.5, y no veo que esto sea una consecuencia de cualquiera de ellos.


Fresco de una regeneración completa del índice, el problema persiste:

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)

Tenga en cuenta que yo, literalmente, acaba ANALYZEed, y seqscan está deshabilitado.

¿Fue útil?

Solución

Bueno, pasé un poco de tiempo haciendo algo de espacio extra en el disco con la base de datos, moviendo algunas otras bases de datos a otro SSD.

entonces corrí VACUUM ANALYZE en toda la base de datos, y ahora aparentemente se dio cuenta que tengo el índice.

Anteriormente había analizado y aspirado solo esta mesa, pero aparentemente de alguna manera hizo una diferencia hacerlo en general en lugar de hacerlo en una tabla específica.Imagínate.

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)

También aproveché la oportunidad para realizar un VACUUM FULL; ahora que tengo suficiente espacio para el procesamiento.He tenido bastante rotación de filas en la tabla mientras experimentaba durante el desarrollo y me gustaría intentar consolidar cualquier fragmentación de archivos que haya resultado de eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a dba.stackexchange
scroll top