Índice Full-Text

Un índice full-text permite realizar búsquedas de texto eficientes sobre columnas CHAR, VARCHAR o TEXT. A diferencia de LIKE '%palabra%', que hace un escaneo completo de la tabla, un índice full-text construye una estructura optimizada de palabras que permite búsquedas casi instantáneas. MySQL soporta búsquedas full-text en tablas InnoDB y MyISAM.

Sintaxis

-- Al crear la tabla
CREATE TABLE tabla (
    id INT AUTO_INCREMENT PRIMARY KEY,
    contenido TEXT,
    FULLTEXT INDEX nombre_indice (contenido)
);
 
-- Sobre tabla existente
CREATE FULLTEXT INDEX nombre_indice ON tabla (columna);
 
-- Con ALTER TABLE
ALTER TABLE tabla ADD FULLTEXT INDEX nombre_indice (columna);
 
-- Sobre múltiples columnas
CREATE FULLTEXT INDEX nombre_indice ON tabla (columna1, columna2);

Crear índice full-text en tienda_mysql

Las tablas productos y resenas tienen columnas de texto que se benefician de búsqueda full-text:

-- Índice sobre nombre y descripción de productos
CREATE FULLTEXT INDEX ft_productos ON productos (nombre, descripcion);
 
-- Índice sobre comentarios de reseñas
CREATE FULLTEXT INDEX ft_resenas ON resenas (comentario);
-- Verificar que se crearon
SHOW INDEXES FROM productos WHERE Index_type = 'FULLTEXT';
TableKey_nameColumn_nameIndex_type
productosft_productosnombreFULLTEXT
productosft_productosdescripcionFULLTEXT

Full-text vs LIKE

-- Con LIKE: escaneo completo, lento en tablas grandes
SELECT nombre, precio FROM productos WHERE nombre LIKE '%portátil%' OR descripcion LIKE '%portátil%';
nombreprecio
MacBook Air M31399.00
Lenovo ThinkPad X11549.00
ASUS ROG Zephyrus1899.99
-- Con full-text: usa el índice, rápido
SELECT nombre, precio FROM productos WHERE MATCH(nombre, descripcion) AGAINST('portátil');
nombreprecio
MacBook Air M31399.00
Lenovo ThinkPad X11549.00
ASUS ROG Zephyrus1899.99
MétodoRendimiento en tabla grandeBusca palabras parcialesRelevancia
LIKE '%word%'Lento, full scanNo
FULLTEXTRápido, usa índiceNo
LIKE 'word%'Rápido con índice B-TreeSolo prefijosNo

Columnas compatibles

Los índices full-text solo se pueden crear sobre columnas de texto:

Tipo de columnaFull-textNotas
CHAR-
VARCHAR-
TEXT-
TINYTEXT-
MEDIUMTEXT-
LONGTEXT-
INT, DATE, etc.NoSolo tipos de texto
BLOBNoDatos binarios, no texto

Índice sobre múltiples columnas

Un índice full-text puede cubrir varias columnas. La búsqueda buscará en todas las columnas incluidas:

-- El índice ft_productos cubre nombre y descripcion
-- MATCH debe incluir exactamente las mismas columnas del índice
SELECT nombre, precio
FROM productos
WHERE MATCH(nombre, descripcion) AGAINST('cámara Samsung');
nombreprecio
Samsung Galaxy S24899.99

No puedes usar MATCH(nombre) solo si el índice fue creado sobre (nombre, descripcion). Las columnas en MATCH deben coincidir exactamente con las del índice.

-- Si necesitas buscar solo en nombre, crea un índice separado
CREATE FULLTEXT INDEX ft_nombre ON productos (nombre);
 
-- Ahora puedes buscar solo en nombre
SELECT nombre FROM productos WHERE MATCH(nombre) AGAINST('Samsung');
nombre
Samsung Galaxy S24

Limitaciones

  • La longitud mínima de palabra por defecto es 3 caracteres para InnoDB y 4 para MyISAM
  • Las stopwords son palabras comunes que se ignoran
  • No soporta búsqueda en columnas BLOB
  • Las columnas en MATCH() deben coincidir exactamente con las del índice

Limpieza

DROP INDEX ft_productos ON productos;
DROP INDEX ft_resenas ON resenas;
DROP INDEX ft_nombre ON productos;

En el siguiente artículo veremos las variables de configuración que afectan el rendimiento de las búsquedas full-text.

Escrito por Eduardo Lázaro