tldr:los trigramas pueden no ser buenos para buscar patrones que consisten en un solo carácter repetido N veces (como 666666
) porque solo existe 1 trigrama no terminal y ese podría tener una alta incidencia en el espacio de búsqueda.
Cuando se usa el índice gin, el mapa de bits de las filas es demasiado grande para caber en la memoria, por lo que almacena la referencia a las páginas y la base de datos tiene que realizar un escaneo de revisión adicional sobre estas páginas. Si el número de páginas revisadas es pequeño, el uso del índice sigue siendo beneficioso; sin embargo, con un número alto de páginas revisadas, el índice funciona mal. Esto se destaca en las siguientes líneas en su salida de explicación
Recheck Cond: (x ~~* '%666666%'::text)
Rows Removed by Index Recheck: 36257910
Heap Blocks: exact=39064 lossy=230594
El problema es particular de su cadena de búsqueda, es decir, 666666
, con respecto a los datos de prueba.
si ejecuta select pg_trgm('666666')
, encontrará:
show_trgm
-------------------------
{" 6"," 66","66 ",666}
(1 row)
Los primeros 3 trigramas ni siquiera se generarán en un contexto similar (corrección sugerida por el usuario jjanes ) . La búsqueda en el índice arroja todas las páginas que contienen 666
. Puede validar esto ejecutando la consulta de análisis de explicación con ... ilike '%666%'
y obteniendo los mismos Heap Blocks
salida como arriba.
si buscas con el patrón 123456
, verá que funciona mucho mejor, porque genera un conjunto más grande de trigramas para buscar:
show_trgm
-------------------------------------
{" 1"," 12",123,234,345,456,"56 "}
(1 row)
En mi máquina, obtengo lo siguiente:
|------------------------------------|
| pattern | pages rechecked |
| | exact | lossy | total |
|------------------------------------|
| 123456 | 600 | | 600 |
| 666666 | 39454 | 230592 | 270046* |
| 666 | 39454 | 230592 | 270046* |
|------------------------------------|
*this is rougly 85% of the total # of pages used for the table 't'
Aquí está el resultado de la explicación:
postgres=> explain analyze select * from t where x ~ '123456';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on t (cost=90.75..18143.92 rows=5000 width=22) (actual time=110.962..113.509 rows=518 loops=1)
Recheck Cond: (x ~ '123456'::text)
Rows Removed by Index Recheck: 83
Heap Blocks: exact=600
-> Bitmap Index Scan on t_x_idx (cost=0.00..89.50 rows=5000 width=0) (actual time=110.868..110.868 rows=601 loops=1)
Index Cond: (x ~ '123456'::text)
Planning time: 0.703 ms
Execution time: 113.564 ms
(8 rows)
postgres=> explain analyze select * from t where x ~ '666666';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on t (cost=54.75..18107.92 rows=5000 width=22) (actual time=137.143..18111.609 rows=462 loops=1)
Recheck Cond: (x ~ '666666'::text)
Rows Removed by Index Recheck: 36258389
Heap Blocks: exact=39454 lossy=230592
-> Bitmap Index Scan on t_x_idx (cost=0.00..53.50 rows=5000 width=0) (actual time=105.962..105.962 rows=593708 loops=1)
Index Cond: (x ~ '666666'::text)
Planning time: 0.420 ms
Execution time: 18111.739 ms
(8 rows)
postgres=> explain analyze select * from t where x ~ '666';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on t (cost=54.75..18107.92 rows=5000 width=22) (actual time=102.813..17285.086 rows=593708 loops=1)
Recheck Cond: (x ~ '666'::text)
Rows Removed by Index Recheck: 35665143
Heap Blocks: exact=39454 lossy=230592
-> Bitmap Index Scan on t_x_idx (cost=0.00..53.50 rows=5000 width=0) (actual time=96.100..96.100 rows=593708 loops=1)
Index Cond: (x ~ '666'::text)
Planning time: 0.500 ms
Execution time: 17300.440 ms
(8 rows)