Índices
En resumen: Un índice es una estructura aparte, ordenada, sobre una columna, que permite a la base de datos encontrar las filas que necesita sin leer toda la tabla.
Problema
Vistos recientemente
La tienda ha crecido. Cada vez que alguien abre la página de un producto, se guarda una fila en la tabla visits: qué cliente (customer_id), qué producto (product_id) y cuándo (seen_at). Esta tabla existe solo en este módulo: tiene 5 000 clientes y 300 000 visitas.
La página «Vistos recientemente» pide a la base de datos las visitas de un cliente. Ejecuta la consulta y mira el tiempo bajo el resultado:
Unos milisegundos parecen poco. Pero la página la abren miles de personas, y la tabla crece cada día.
La idea
La base de datos lo lee todo
Las filas de la tabla no están ordenadas por cliente. Para encontrar las 60 visitas del cliente 1234, la base de datos lee las 300 000 filas y comprueba cada una.
Imagina que buscas la palabra «índice» en un libro de texto sin índice al final. Tendrías que pasar todas las páginas. Por eso un libro tiene al final un índice alfabético: las palabras están ordenadas, y junto a cada una están las páginas donde aparece.
Un índice de una tabla es lo mismo. Es una copia aparte, ordenada, de una columna, donde cada valor lleva una nota con el lugar de su fila. Como está ordenado, la base de datos busca partiendo por la mitad: mira en el medio, deduce en qué mitad está 1234, mira en el medio de esa mitad, y así sucesivamente. Para 300 000 valores bastan unos 19 pasos.
Aquí lo ves en una tabla pequeña con seis visitas, primero sin índice y luego con uno:
SELECT * FROM visits WHERE customer_id = 3;CREATE INDEX idx_visits_customer ON visits(customer_id);SELECT * FROM visits WHERE customer_id = 3;Paso a paso, en palabras
- 6 visitas. Las filas no están ordenadas por customer_id: 5, 3, 8, 3, 1, 6.
- Sin índice, la base de datos hace un SCAN: lee fila por fila y compara customer_id con 3.
- Se leyeron 6 filas de 6, y coinciden 2: las filas con id 2 y 4.
- CREATE INDEX crea una copia ordenada de customer_id: 1, 3, 3, 5, 6, 8. Junto a cada valor anota de qué fila es.
- Con el índice es un SEARCH. En el medio está 5, más que 3: así que 3 está en la mitad de los valores menores, por encima de 5.
- En el medio de esa mitad está 3. Encima está 1, que es menor: este es el primer 3.
- Junto a 3 está la fila 2, junto al siguiente 3 la fila 4. Luego 5: terminado. De la tabla se leen solo 2 filas.
Un índice se crea con CREATE INDEX nombre ON tabla(columna). Ejecuta el campo dos veces y compara los tiempos:
La primera vez se construye el índice, por eso es lenta. En la segunda el índice ya existe (IF NOT EXISTS se salta la creación, como en CREATE TABLE), y solo queda la búsqueda. Compárala con el tiempo de la consulta sin índice de la tarjeta anterior: la diferencia es de cientos de veces.
Más precisamente, para curiosos
Los índices de SQLite, PostgreSQL, MySQL y SQL Server son por defecto árboles B. No es una lista que se parte por la mitad, sino un árbol de páginas: cada página contiene cientos de valores ordenados y apunta al nivel siguiente. Por eso, incluso con millones de filas bastan tres o cuatro lecturas de página. La idea es la misma: ordenado, y cada paso descarta casi todo lo que no hace falta.
Pruébalo
Cuántas veces se ve un producto
La página de cada producto va a mostrar cuántas veces se ha visto. Crea un índice que acelere la búsqueda por producto y cuenta después las visitas del producto 7.
Solución
CREATE INDEX idx_visits_product ON visits(product_id);
SELECT COUNT(*) FROM visits WHERE product_id = 7;CREATE INDEX idx_visits_product ON visits(product_id); El nombre lo eliges tú. Lo habitual es el patrón idx_<tabla>_<columna>, para que se entienda qué es. El producto 7 se ha visto 12 000 veces. Aquí la mejora es menor que con el cliente, porque la condición elige el 4 % de la tabla, no 60 filas. Un índice ayuda más cuando buscas pocas filas entre muchas.
La idea
Índices que ya tienes
La búsqueda por clave primaria es rápida sin CREATE INDEX:
En SQLite una columna INTEGER PRIMARY KEY es el orden de la propia tabla: las filas se guardan por id. Así que no hace falta un índice aparte.
Para UNIQUE la base de datos crea un índice por su cuenta. Sin él, cada correo nuevo obligaría a leer todos los clientes para comprobar si ya existe. SQLite guarda la descripción de la base de datos en la tabla sqlite_master. Mira qué índices tiene la tienda:
El primero es el de email en customers. El segundo es el de la clave primaria de order_items, que tiene dos columnas (order_id, product_id) y no es un INTEGER PRIMARY KEY.
Míralo
DROP INDEX
Un índice se elimina con DROP INDEX nombre. Los datos no cambian: solo desaparecen el índice y la búsqueda rápida. En este campo el índice sobre el cliente ya está creado. Ejecuta la consulta y mira el tiempo:
El tiempo vuelve a ser el de antes, sin índice. Si ejecutas el campo una segunda vez, SQLite dirá que no existe ese índice. El botón «Base nueva» devuelve el estado inicial.
Ejercicio
Dos tareas
1. El informe «visitas por día» se ejecuta cada mañana. Crea un índice que lo acelere y cuenta con él las visitas del 1 de marzo de 2026.
Un índice para buscar por fecha, y el número de visitas del 2026-03-01:
Solución
CREATE INDEX idx_visits_seen ON visits(seen_at);
SELECT COUNT(*) FROM visits WHERE seen_at = '2026-03-01';CREATE INDEX idx_visits_seen ON visits(seen_at); El 1 de marzo de 2026 hay 454 visitas.
2. Se ha desactivado la página con el número de vistas de un producto. La base de datos tiene dos índices: idx_visits_customer e idx_visits_product. Elimina el que ya no hace falta.
Elimina el índice que nadie usa:
Solución
DROP INDEX idx_visits_product;DROP INDEX idx_visits_product; ¿Por qué eliminar un índice, si no estorba al leer? Porque cada índice se actualiza en cada escritura y ocupa espacio. Cuánto, lo medirás en la lección sobre índices de varias columnas.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Clave primaria y clave foránea · CREATE TABLE: crear una tabla · Restricciones: reglas para los datos · ALTER TABLE: cambiar una tabla
- Continúa en: EXPLAIN: el plan de la consulta · Índices de varias columnas · Consultas lentas · OLTP y OLAP
- Ejercicios sobre el tema: Índices y velocidad