SQL · índices y rendimiento

Índices sobre expresiones o índices funcionales

Acelera búsquedas que filtran u ordenan por una transformación calculada, como LOWER(email), sin confundir un índice sobre expresión con una columna normal o un índice parcial.

Lectura: 6–8 minSQL comprobadoPráctica con pistas
Contenido de esta guía

Respuesta rápida

Un índice sobre expresión guarda claves derivadas de una expresión calculada a partir de las columnas de la fila. Sirve cuando la consulta repite esa misma transformación en WHERE u ORDER BY.

Ejemplo en SQLite y PostgreSQL
CREATE INDEX idx_clientes_email_lower
ON clientes(lower(email));

SELECT id, nombre, email
FROM clientes
WHERE lower(email) = 'ana@example.test';

El índice no cambia el valor almacenado en email. Mantiene una estructura adicional con el resultado de lower(email) para que el motor pueda localizar coincidencias sin recalcular y revisar toda la tabla cuando el planificador considere útil el índice.

Modelo mental: indexa la forma en la que realmente buscas

Un índice convencional sobre email contiene el valor de la columna. Si tu condición siempre aplica lower(email), la expresión consultada ya no es simplemente email. Un índice funcional permite indexar esa forma derivada.

No es una mejora automática. Cada índice ocupa espacio y debe mantenerse en inserciones y actualizaciones. Créalo porque una consulta real y frecuente lo necesita, no porque exista una función que puedas indexar.

Ejemplo comprobado: búsqueda de email sin distinguir mayúsculas

Sobre la base educativa, el siguiente índice y consulta fueron comprobados dentro de una transacción y revertidos después de la prueba:

Índice + consulta
CREATE INDEX idx_clientes_email_lower_demo
ON clientes(lower(email));

EXPLAIN QUERY PLAN
SELECT id, nombre, email
FROM clientes
WHERE lower(email) = 'ana@example.test';
Plan observado en SQLite 3.46.1
detail
SEARCH clientes USING INDEX idx_clientes_email_lower_demo (<expr>=?)

El plan confirma que SQLite reconoce el índice para la expresión consultada. La consulta devuelve a Ana Torres con ana@example.test.

La expresión de la consulta debe encajar con la indexada

SQLite documenta una regla especialmente estricta: el planificador no hace álgebra para demostrar que dos expresiones equivalentes son la misma. Si indexas x + y y consultas y + x, puede no usar el índice aunque la suma sea matemáticamente equivalente.

En la práctica, conserva una forma estable para las expresiones indexadas y comprueba el plan real con EXPLAIN o la herramienta equivalente del motor.

Crear el índice y asumir que toda variante lo usará

Un índice disponible no obliga al optimizador a elegirlo. Además de la expresión, influyen selectividad, tamaño de tabla, estadísticas y coste estimado. Verifica la consulta que importa.

Diferencias entre motores

  • PostgreSQL: CREATE INDEX acepta expresiones y exige que las funciones y operadores usados en la definición sean inmutables.
  • SQLite: permite índices sobre expresiones deterministas y exige una coincidencia muy cercana entre la expresión del índice y la de la consulta.
  • MySQL 8.4: admite functional key parts; la expresión se escribe entre paréntesis adicionales, por ejemplo CREATE INDEX idx ON tabla ((LOWER(columna))), y hereda restricciones de columnas generadas.
  • SQL Server: el patrón habitual es definir una columna calculada que cumpla requisitos de determinismo/precisión y crear el índice sobre esa columna.

Por eso «índice funcional» describe una intención común, pero la sintaxis exacta no es portable entre los cuatro motores.

Cuándo merece la pena

  • Filtros frecuentes por LOWER(columna) u otra normalización estable.
  • Ordenaciones repetidas por una expresión calculada.
  • Reglas de unicidad sobre una transformación cuando el motor lo permite y la semántica está bien definida.

No lo confundas con un índice compuesto, que combina varias claves, ni con un índice parcial/filtrado, que incluye solo las filas que cumplen un predicado. Un índice puede combinar varias ideas, pero cada una resuelve un problema distinto.

Práctica: indexa una búsqueda normalizada por ciudad

Intermedia · rendimiento

Prepara un índice para LOWER(ciudad)

Escribe un índice sobre lower(ciudad) y una consulta que busque 'madrid' usando exactamente la misma expresión. Después comprueba el plan en tu motor.

Qué debes recordar

  • Indexa una expresión cuando las consultas reales filtran u ordenan por esa expresión.
  • La forma de la consulta debe ser compatible con la forma indexada.
  • Comprueba el plan: que el índice exista no garantiza su uso.
  • La sintaxis y las restricciones cambian bastante entre motores.

Conceptos relacionados

Fuentes técnicas consultadas

Las referencias oficiales se usaron para verificar sintaxis, restricciones y comportamiento del planificador.