2012-08-25 22 views
6

Tengo una consulta con un número de campos de prueba de algo como esto:Postgresql ILIKE frente tsearch

SELECT * FROM some-table 
    WHERE field1 ILIKE "%thing%" 
    OR field2 ILIKE "%thing" 
    OR field3 ILIKE "%thing"; 

Las columnas son más o menos todo varchar (50), más o menos. Ahora entiendo que para mejorar el rendimiento debería indexar los campos sobre los que opera la búsqueda. ¿Debería considerar reemplazar ILIKE por TSEARCH por completo?

Respuesta

15

Una configuración de búsqueda de texto completo no es idéntica a una consulta de tipo "contiene". Se derivan palabras, etc. por lo que puede hacer coincidir "autos" contra "automóvil".

Si realmente quiere un ILIKE rápido, entonces ningún índice de base de datos estándar o FTS lo ayudará. Afortunadamente, el módulo pg_trgm puede hacer eso.

+0

pg_trgm es muy útil. Para usuarios de Django: index on 'upper (your_text_field)' porque Django emite 'upper (x) como upper (y)' consultas en lugar de 'ilike'. Si el campo está indexado sin 'superior', el índice no se usará en esas consultas. – Risadinha

5

Una cosa que es muy importante: NO índice B-tree volverá a mejorar este tipo de búsqueda:

where field ilike '%SOMETHING%' 

Lo que estoy diciendo es que si lo hace un:

create index idx_name on some_table(field); 

El único acceso que mejorará es where field like 'something%'. (cuando busca valores comenzando con algún literal). Por lo tanto, no obtendrás ningún beneficio al agregar un índice regular a la columna field en este caso.

Si necesita mejorar el tiempo de respuesta de búsqueda, definitivamente considere usar BÚSQUEDA DE TEXTO COMPLETO.

+0

Tiene razón en que ningún B-Tree mejorará esa búsqueda, pero PostgreSQL puede usar otros tipos de índice para admitir una condición '% foobar%' (vea la respuesta de Richard) –

3

Añadiendo un poco a lo que los otros han dicho.

Primero, realmente no se puede usar un índice basado en un valor en el medio de la cadena. Los índices generalmente son búsquedas en árbol, y usted no tiene forma de saber si su búsqueda será más rápida que solo escanear la tabla, por lo que PostgreSQL realizará de manera predeterminada un escaneo seq. Los índices solo se usarán si coinciden con la primera parte de la cadena. Por lo tanto:

SELECT * FROM invoice 
    WHERE invoice_number like 'INV-2012-435%' 

puede utilizar un índice, pero no puede like '%44354456%'.

En general, en LedgerSMB utilizamos ambos, dependiendo de qué tipo de búsqueda estamos haciendo. Es posible que vea una búsqueda como:

select * from parts 
    WHERE partnumber ilike ? || '%' 
    and plainto_tsquery(get_default_language(), ?) @@ description; 

Por lo tanto, estos son muy diferentes. Use cada uno donde tenga más sentido.

+1

Acepto que no hay suficiente información para estar seguro de si trigram o tsearch es más apropiado, pero uno u otro (o posiblemente una combinación) parece indicado. – kgrittn

Cuestiones relacionadas