¿Por qué mi tsv índice que no están siendo utilizados?
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 ANALYZE
ed, y seqscan está deshabilitado.
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.