Hola Guillermo
On 10/08/16 12:32, Guillermo E. Villanueva wrote:
Buenas tardes , he leído sobre el tema Postgres y FTS en varios sitios
y lo he utilizado varias veces pero al decir verdad, sigo
entendiendolo muy poco.
Si alguno tiene tiempo y puede ayudarme, les comento mi inquietud.
Tengo la siguiente consulta:
SELECT *
FROM tescrito t
WHERE to_tsvector('spanish',escritodtxt) @@
to_tsquery('spanish','*salta*')
y tengo un índice creado
CREATE INDEX fts_escritodtxt ON public.tescrito
USING gin (to_tsvector('spanish'::regconfig, escritodtxt));
La tabla tiene 65300 registros
El planificado me dice que realizará un seq scan y de hecho, la
consulta demora mucho.
Si cambio la palabra a buscar, por ejemplo por 'casa'
SELECT *
FROM tescrito t
WHERE to_tsvector('spanish',escritodtxt) @@
to_tsquery('spanish','*casa*')
Entonces demora menos y el planificador ahora dice que si utilizará el
índice.
Preguntas:
En que se basa postgres para decidir si utiliza o no el índice si lo
único que cambié es la palabra a buscar?
Tengo entendido que se basa en las estadísticas para ver si usa el
indice o no, por ejemplo puede que el optimizador considere que es
mejor escanear la tabla completa antes de usar un indice, pues el
resultado está en un porciento grande de la tabla ( no se el porciento
exacto :( ), ejemplo:
De:
explain analyze
select * from customers where customerid >10000
Obtenemos:
"Index Scan using customers_pkey on customers (cost=0.29..538.29
rows=10000 width=268) (actual time=0.019..1.764 rows=10000 loops=1)"
" Index Cond: (customerid > 10000)"
"Planning time: 0.113 ms"
"Execution time: 2.064 ms"
Y de:
explain analyze
select * from customers where customerid >1000
Obtenemos:
"Seq Scan on customers (cost=0.00..738.00 rows=19000 width=268) (actual
time=0.273..3.120 rows=19000 loops=1)"
" Filter: (customerid > 1000)"
" Rows Removed by Filter: 1000"
"Planning time: 0.189 ms"
"Execution time: 3.640 ms"
Como ves con solo cambiar el valor del customerid el optimizador usa el
indice o no, y este optimizador de PostgreSQL ha resultado ser inteligente.
pero si consideras tu que no esta bien la decisión del optimizador
puedes "tomar el toro por los cuernos" y obligarlo a que use el indice
por ejemplo:
set enable_seqscan = off;
explain analyze
select * from customers where customerid >1000;
Obtenemos:
"Index Scan using customers_pkey on customers (cost=0.29..1019.79
rows=19000 width=268) (actual time=0.013..5.099 rows=19000 loops=1)"
" Index Cond: (customerid > 1000)"
"Planning time: 0.076 ms"
"Execution time: 5.820 ms"
vaya que se demora más con el indice que con el scan para el customerid
>1000
Será que el tsquery de 'salta' es una palabra que no se indexa?
el to_tsvector obtiene los siguientes lexemas(donde esta 'salta'):
SELECT to_tsvector('spanish','saltar un muro que es bien alto');
"'alto':7 'bien':6 'mur':3 'salt':1"
puede que 'salt' que es el lexema de 'salta' sea un porciento grande de
la tabla y por eso el decide no usar el indice (de todos modos puedes
forzarlo a usar el indice con set enable_seqscan = off; , vaya ser que
se equivoque el optimizador, prueba a ver si se equivoca el optimizador )
Para el caso de 'spanish' Aparte de crear el índice es necesario crear
o configurar algo mas?
hasta donde yo lo he usado no me ha sido necesario configurar más nada,
pero puede que haya que hacer algo más para lo que requieres
Desde ya les agradezco la ayuda que me puedan brindar.
Saludos
Guillermo
Saludos