El desarrollo está en marcha, por lo que no hay trucos de optimización fiables a largo plazo. Algunos trucos interesantes que puede usar son:
Use cláusulas de subconsulta que afecten al número u orden de los registros en la subconsulta. Por ejemplo:
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
Reemplace un join con una subconsulta. Por ejemplo, pruebe:
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN ( SELECT column1 FROM t2);
En lugar de:
SELECT DISTINCT t1.column1 FROM t1, t2 WHERE t1.column1 = t2.column1;
Algunas subconsultas pueden transformarse en joins por compatibilidad con versiones anteriores de MySQL que no soportan subconsultas. Sin embargo, en algunos casos, incluso en MySQL 5.0, convertir una subconsulta en un join puede mejorar el rendimiento. Consulte Sección 13.2.8.11, “Re-escribir subconsultas como joins en versiones de MySQL anteriores”.
Mueva las cláusulas desde fuera hacia dentro en la subconsulta. Por ejemplo , use esta consulta:
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
En lugar de:
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
Otro ejemplo. Use esta consulta:
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
En lugar de:
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
Use una subconsulta de registro en lugar de una subconsulta correlacionada . Por ejemplo, use:
SELECT * FROM t1 WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
En lugar de:
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1 AND t2.column2=t1.column2);
Use NOT (a = ANY (...))
en lugar de
a <> ALL (...)
.
Use x = ANY (table containing (1,2))
en
lugar de x=1 OR x=2
.
Use = ANY
en lugar de
EXISTS
.
Para subconsultas no correlacionadas que siempre retornan
un registro, IN
siempre es más lento
que =
. Por ejemplo, use esta consulta:
SELECT * FROM t1 WHERE t1.col_name
= (SELECT a FROM t2 WHERE b =some_const
);
En lugar de:
SELECT * FROM t1 WHERE t1.col_name
IN (SELECT a FROM t2 WHERE b =some_const
);
Estos trucos pueden hacer que los programas vayan más
rápidos o lentos. Usar recursos MySQL como la función
BENCHMARK()
es una buena idea para ver
cuáles funcionan.
Algunas optimizaciones que realiza MySQL son:
MySQL ejecuta subconsultas no correlacionadas sólo una
vez. Use EXPLAIN
para asegurar que una
subconsulta dada realmente no está correlacionada.
MySQL reescribe subconsultas IN
,
ALL
, ANY
, y
SOME
para aprovechar que las columnas
de la lista de select de la subconsulta está indexada.
MySQL reemplaza subconsultas de la siguiente forma con una
función de búsqueda de índice, que
EXPLAIN
describe como tipo especial de
join (unique_subquery
o
index_subquery
):
... IN (SELECTindexed_column
FROMsingle_table
...)
MySQL mejora expresiones de la siguiente forma con una
expresión que involucre MIN()
o
MAX()
, a no ser que hayan involucrados
valores NULL
o conjuntos vacíos:
value
{ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery
)
Por ejemplo, esta cláusula WHERE
:
WHERE 5 > ALL (SELECT x FROM t)
puede tratarse por el optimizador como:
WHERE 5 > (SELECT MAX(x) FROM t)
Hay un capítulo titulado “Cómo transforma las
subconsultas MySQL” en el manual MySQL Internals
Manual. Puede obtener este documento descargando el paquete
fuente MySQL y buscando un fichero llamado
internals.texi
en el directorio
Docs
.
Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.