Capítulo 8: Optimización

Optimización de consultas

Una sencilla consulta:

USE videoteca;

SELECT
  *
FROM
  pelicula
WHERE
  titulo = 'Blade Runner';

Plan de ejecución

Para ver qué hace una consulta:

USE videoteca;

EXPLAIN
SELECT
  *
FROM
  pelicula
WHERE
  titulo = 'Blade Runner'G

Índices

Crear un índice para el título:

USE videoteca;

ALTER TABLE
  pelicula
ADD INDEX
  pelicula_titulo_indice(titulo);

Crear el índice, dándole un nombre más corto:

USE videoteca;

ALTER TABLE
  pelicula
ADD INDEX
  pt_I(titulo);

Índices únicos

Crear la tabla de intérpretes con un índice único:

USE videoteca;

CREATE TABLE interprete
(
  id INT NOT NULL AUTO_INCREMENT,
  nombre VARCHAR(64) NOT NULL,
  apellidos VARCHAR(64) NOT NULL,
  imdb VARCHAR(32) NOT NULL DEFAULT '',
  PRIMARY KEY(id),
  UNIQUE INDEX ii_UI(imdb)
)
ENGINE = InnoDB;

O modifica el diseño de la existente:

USE videoteca;

ALTER TABLE
  interprete
ADD UNIQUE INDEX
  ii_UI(imdb);

Lo mismo con los directores:

USE videoteca;

ALTER TABLE
  director
ADD UNIQUE INDEX
  di_UI(imdb);

Índice de texto

Tabla intermedia:

USE videoteca;

CREATE TABLE lomo
(
  idpelicula INT NOT NULL,
  titulo VARCHAR(64) NOT NULL,
  PRIMARY KEY(idpelicula),
  FULLTEXT INDEX lt_FT(titulo)
)
ENGINE = InnoDB;

Llenado inicial de la tabla:

USE videoteca;

INSERT INTO
  lomo(idpelicula, titulo)
SELECT
  id,
  titulo
FROM
  pelicula;

Uso del índice:

USE videoteca;

SELECT
  *
FROM
  lomo
WHERE
  MATCH(titulo) AGAINST('blade');

Otro uso del índice:

USE videoteca;

SELECT
  p.*
FROM
  pelicula p
  JOIN lomo l ON p.id = l.idpelicula
WHERE
  MATCH(l.titulo) AGAINST('blade');

Borrado de índices

Este índice ya no sirve:

USE videoteca;

ALTER TABLE
  pelicula
DROP INDEX
  pt_I;

Información sobre índices

Descripción de una tabla:

USE videoteca;

DESCRIBE lomo;

Detalles de los índices:

USE videoteca;

SHOW INDEX FROM lomo;

Consulta de todos los detalles de una película:

USE videoteca;

SELECT
  p.titulo pelicula,
  s.nombre soporte,
  g.descripcion genero,
  CONCAT(d.nombre, ' ', d.apellidos) director,
  CONCAT(i.nombre, ' ', i.apellidos) interprete
FROM
  pelicula p
  JOIN genero g ON p.idgenero = g.id
  JOIN soporte s ON p.idsoporte = s.id
  JOIN directores_por_pelicula dpp ON p.id = dpp.idpelicula
  JOIN director d ON dpp.iddirector = d.id
  JOIN interpretes_por_pelicula ipp ON p.id = ipp.idpelicula
  JOIN interprete i ON ipp.idinterprete = i.id
WHERE
  p.titulo = 'Blade Runner';

Obligar a utilizar las tablas en el orden indicado:

USE videoteca;

SELECT STRAIGHT_JOIN
  p.titulo pelicula,
  s.nombre soporte,
  g.descripcion genero,
  CONCAT(d.nombre,' ', d.apellidos) director,
  CONCAT(i.nombre,' ', i.apellidos) interprete
FROM
  pelicula p
  JOIN genero g ON p.idgenero = g.id
  JOIN soporte s ON p.idsoporte = s.id
  JOIN directores_por_pelicula dpp ON p.id = dpp.idpelicula
  JOIN director d ON dpp.iddirector = d.id
  JOIN interpretes_por_pelicula ipp ON p.id = ipp.idpelicula
  JOIN interprete i ON ipp.idinterprete = i.id
WHERE
  p.titulo = 'Blade Runner';
Anuncios