lunes, 23 de mayo de 2011

Bajo rendimiento de consulta Oracle con upper

Hace poco estaba trabajando, y tenía una consulta sobre mi base de datos Oracle, que obtenía una sería de datos haciendo un filtrado por un campo de tipo varchar2. La consulta parecía funcionar bien, y tenía un rendimiento perfectamente aceptable. Algo como:

select * from tabla where campo=:parametro

Pero al poco tiempo me di cuenta de que para que la consulta funcionase correctamente en todos los casos, necesitaba que no se distinguiese entre mayúsculas y minúsculas al hacer la comparación. Por tanto, añadí una llamada a upper para el campo (el parámetro siempre llega en mayúsculas).

select * from tabla where upper(campo)=:parametro

De esta forma la consulta funcionaba como yo necesitaba. El problema es que, para mi sorpresa, el rendimiento cayó en picado.

En principio busqué la explicación en la llamada a upper en sí, pero lógicamente este tratamiento no es tan pesado como para producir tanto retraso. El problema está en que el buen tiempo de respuesta de la consulta original se producía gracias a la existencia de un índice sobre la columna campo. Al pasar a hacer la comparación por upper(campo), Oracle no puede utilizar el índice, y el tiempo de respuesta crece exponencialmente.

Ante esta situación, una solución es crear un índice directamente sobre la expresión upper(campo), en lugar (o además) de directamente sobre campo.

create index campo_index on tabla (upper(campo))

Eso sí, hay que tener en cuenta que para que el índice sea utilizado en este caso, es necesario modificar ligeramente la consulta, y asegurarse de que no se obtienen valores nulos.

No hay comentarios:

Publicar un comentario

Cualquier aportación será bienvenida