这个SQL查询需要230.63秒(差不多4分钟!)。
SELECT SQL_CALC_FOUND_ROWS vino.ID, detalle, nombre, do, vino.ID_do, anada,
tamano_texto, vino.ID_tamano, precio, imagen_principal, vino.ID_imagen_principal,
imagen_principal_tn, imagen_detalle, vino.ID_imagen_detalle, imagen_detalle_tn,
vino.ID_tipo, tipo_texto, vino.ID_pais, pais_texto, precio_copa, precio_tienda FROM vino
INNER JOIN almacen ON almacen.ID_categoria = 1 AND ID_articulo = vino.ID AND unidades > 0
LEFT OUTER JOIN vino_componente ON vino_componente.ID_vino = vino.ID
LEFT OUTER JOIN componente_texto ON componente_texto.ID_componente = vino_componente.ID_componente AND componente_texto.ID_idioma = 1
LEFT OUTER JOIN do ON vino.ID_do = do.ID
LEFT OUTER JOIN tamano ON vino.ID_tamano = tamano.ID
LEFT OUTER JOIN tamano_texto ON tamano_texto.ID_tamano = tamano.ID AND tamano_texto.ID_idioma = 1
LEFT OUTER JOIN imagen_principal ON vino.ID_imagen_principal = imagen_principal.ID
LEFT OUTER JOIN imagen_detalle ON vino.ID_imagen_detalle = imagen_detalle.ID
LEFT OUTER JOIN tipo ON vino.ID_tipo = tipo.ID
LEFT OUTER JOIN tipo_texto ON tipo_texto.ID_tipo = tipo.ID AND tipo_texto.ID_idioma = 1
LEFT OUTER JOIN pais ON vino.ID_pais = pais.ID
LEFT OUTER JOIN pais_texto ON pais_texto.ID_pais = pais.ID AND pais_texto.ID_idioma = 1
WHERE activo = 1 AND (
nombre LIKE "%blanco%"
OR do LIKE "%blanco%"
OR vino.ID IN (
SELECT ID_vino FROM vino_componente
WHERE componente_texto LIKE "%blanco%"
)
OR anada LIKE "%blanco%"
OR tamano_texto LIKE "%blanco%"
)
ORDER BY tipo.orden_papel, vino.ID_pais, do, precio LIMIT 30;
这是EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY almacen ALL NULL NULL NULL NULL 3583 Using where; Using temporary; Using filesort
1 PRIMARY vino eq_ref PRIMARY PRIMARY 4 almacen.ID_articulo 1 Using where
1 PRIMARY vino_componente ALL NULL NULL NULL NULL 6101
1 PRIMARY componente_texto ALL NULL NULL NULL NULL 1103
1 PRIMARY do eq_ref PRIMARY PRIMARY 4 vino.ID_do 1
1 PRIMARY tamano eq_ref PRIMARY PRIMARY 4 vino.ID_tamano 1 Using index
1 PRIMARY tamano_texto ALL NULL NULL NULL NULL 95 Using where
1 PRIMARY imagen_principal eq_ref PRIMARY PRIMARY 4 vino.ID_imagen_principal 1
1 PRIMARY imagen_detalle eq_ref PRIMARY PRIMARY 4 vino.ID_imagen_detalle 1
1 PRIMARY tipo eq_ref PRIMARY PRIMARY 4 vino.ID_tipo 1
1 PRIMARY tipo_texto ref ID_tipo ID_tipo 5 tipo.ID 2
1 PRIMARY pais eq_ref PRIMARY PRIMARY 4 vino.ID_pais 1 Using index
1 PRIMARY pais_texto ALL NULL NULL NULL NULL 553
2 DEPENDENT SUBQUERY vino_componente ALL NULL NULL NULL NULL 6101 Using where
如果我删除嵌套" IN(SELECT)"从WHERE子句开始,它会下降到更合理的8秒,这仍然很慢,但不是那么可笑。但
那么为什么这种工作如此缓慢?如何才能提高速度以获得更好的速度呢?
答案 0 :(得分:1)
查看你的'Explain'结果,有很多'key'列NULL表示某些表上没有索引键,尝试在这些表的字段上创建索引,这将加快查询的执行速度。
请参阅“添加KEY”的CREATE TABLE语法。或者请参阅ALTER TABLE语法以添加新密钥。
答案 1 :(得分:0)
如果来自WHERE子句的内部“IN(SELECT)”导致你的大部分问题尝试首先选择并保存到临时表然后检查临时表...对于这个问题它可能加速事情最多只能制作一个包含所有“LIKE”%blanco%“”行的表,然后你可以通过这些行来加入。我已经看到使用一个或两个临时表来快速加速这样的事情。
答案 2 :(得分:0)
如何使用JOIN:
LEFT OUTER JOIN (
SELECT ID_vino
FROM vino_componente
) vc ON vc.ID_vino = vino.ID
而不是:
LEFT OUTER JOIN vino_componente ON vino_componente.ID_vino = vino.ID
这样所有JOIN只选择特定字段。但是,我确信问题是LIKE关键字。
答案 3 :(得分:0)
好吧,我终于找到了一种方法来加快速度,使用GROUP_CONCAT,GROUP BY和HAVING的组合来替换正在执行数千次的嵌套SELECT(每条记录一次)。
现在查询仍然没有快速(运行需要10秒钟),但它不是那么慢(以前,它花了差不多4分钟),所以它还是一个漂亮的大改进!
SELECT SQL_CALC_FOUND_ROWS vino.ID, detalle, nombre, do, vino.ID_do, anada, tamano_texto, vino.ID_tamano, precio, imagen_principal, vino.ID_imagen_principal, imagen_principal_tn, imagen_detalle, vino.ID_imagen_detalle, imagen_detalle_tn, vino.ID_tipo, tipo_texto, vino.ID_pais, pais_texto, precio_copa, precio_tienda,
GROUP_CONCAT(componente_texto) AS csv_componente_texto
FROM vino
INNER JOIN almacen ON almacen.ID_categoria = 1 AND ID_articulo = vino.ID AND unidades > 0
LEFT OUTER JOIN vino_componente ON vino_componente.ID_vino = vino.ID
LEFT OUTER JOIN componente_texto ON componente_texto.ID_componente = vino_componente.ID_componente AND componente_texto.ID_idioma = 1
LEFT OUTER JOIN do ON vino.ID_do = do.ID
LEFT OUTER JOIN tamano ON vino.ID_tamano = tamano.ID
LEFT OUTER JOIN tamano_texto ON tamano_texto.ID_tamano = tamano.ID AND tamano_texto.ID_idioma = 1
LEFT OUTER JOIN imagen_principal ON vino.ID_imagen_principal = imagen_principal.ID
LEFT OUTER JOIN imagen_detalle ON vino.ID_imagen_detalle = imagen_detalle.ID
LEFT OUTER JOIN tipo ON vino.ID_tipo = tipo.ID
LEFT OUTER JOIN tipo_texto ON tipo_texto.ID_tipo = tipo.ID AND tipo_texto.ID_idioma = 1
LEFT OUTER JOIN pais ON vino.ID_pais = pais.ID
LEFT OUTER JOIN pais_texto ON pais_texto.ID_pais = pais.ID AND pais_texto.ID_idioma = 1
WHERE activo = 1
GROUP BY vino.ID
HAVING nombre LIKE '%blanco%'
OR do LIKE '%blanco%'
OR csv_componente_texto LIKE '%blanco%'
OR anada LIKE '%blanco%'
OR tamano_texto LIKE '%blanco%'
ORDER BY tipo.orden_papel, vino.ID_pais, do, precio
LIMIT 30;
根据其他人提供的答案,没有人像我自己的答案那样真正解决问题,所以我不会将其中任何一个标记为正确,尽管@skstar的建议可能有助于进一步提升绩效所以我已经投票了。谢谢你的帮助。