Índices14 temas

Índices

Un índice es una estructura de acceso auxiliar que permite encontrar filas sin escanear la tabla completa. Funciona como el índice de un libro: vas directo a la página sin leer todo.


Sin índice vs con índice

Clave:

La base de datos no sabe dónde está el registro que cumple la condición. Por eso recorre la tabla secuencialmente: lee fila a fila, evalúa la condición y sigue hasta terminar.

-- Sin índice: la BD no sabe dónde está el email → recorre TODAS las filas (Seq Scan)
SELECT * FROM usuarios WHERE email = 'ana@ejemplo.com';
Full Table Scan sin índice: la consulta recorre cada fila en orden físico, evalúa la condición y devuelve solo las tuplas que la cumplen
-- Con índice: la BD salta directo a la fila (Index Scan)
CREATE INDEX idx_usuarios_email ON usuarios (email);
Acceso por índice
Escenario Seq Scan Index Scan
Tabla chica (< 10k filas) Rápido Overhead innecesario
Tabla grande, filtro selectivo Lento Rápido
Tabla grande, filtro no selectivo A veces mejor Peor (lee índice + tabla)

Selectividad

La selectividad mide qué tan bien un filtro reduce la cantidad de filas. Un campo con alta selectividad devuelve muy pocas filas (idealmente una); uno con baja selectividad devuelve muchas.

-- Alta selectividad → el índice sirve
WHERE email = 'ana@ejemplo.com'        -- único, busca 1 entre millones
WHERE dni = '12345678'                 -- clave única
WHERE id_pedido = 4521                 -- PK / único

-- Baja selectividad → el índice NO sirve
WHERE activo = true                     -- la mitad de la tabla
WHERE genero = 'M'                      -- ~50%
WHERE creado_anio = 2024                -- un año entero de datos
WHERE estado IN ('activo', 'pendiente') -- la mayoría

Si el filtro no descarta casi nada, el optimizador prefiere Seq Scan: leer el índice y luego saltar a la tabla (heap) cuesta más que escanear directo.


B-Tree (el estándar)

Mantiene los valores ordenados y organizados en niveles para descartar grandes grupos de datos rápidamente.

Estructura B-Tree simplificada
Regla:

La mayoría de motores usan B+Tree por defecto.


Trade-off

Operación Con índice Sin índice
INSERT +1-2 escrituras (heap + índice) 1 escritura
UPDATE (columna indexada) +1-2 escrituras 1 escritura
DELETE +1 escritura (marcar en índice) 1 escritura
SELECT (filtrado) O(log N) O(N)

Regla práctica: indexa columnas que filtras en WHERE, JOIN, ORDER BY. Mide con EXPLAIN ANALYZE. Elimina índices no usados (pg_stat_user_indexes).


Índices compuestos (multi-columna)

-- Orden importa: izquierda a derecha
CREATE INDEX idx_pedidos_cliente_fecha ON pedidos (cliente_id, fecha);
Query Usa índice?
WHERE cliente_id = 5 ✅
WHERE cliente_id = 5 AND fecha > '2024-01-01' ✅
WHERE fecha > '2024-01-01' ❌ (no empieza por cliente_id)