我有一个带有多个子查询的查询,运行速度非常慢。
SELECT DISTINCT pav.products_options_values_id,
pav.products_options_values_name,
pav.products_options_values_sort_order
FROM products_stock ps,
products_options_values pav,
(
SELECT DISTINCT pa.products_id,
pov.products_options_values_id,
pov.products_options_values_name,
pa.options_values_price,
pa.price_prefix
FROM products_attributes pa,
products_options_values pov,
(
SELECT DISTINCT p.products_image,
p.products_quantity,
p.products_status,
m.manufacturers_id,
p.products_id,
p.products_date_added,
p.products_subimage1,
pd.products_name,
p.products_price,
p.products_length,
p.products_width,
p.products_height,
p.products_tax_class_id,IF(s.status, s.specials_new_products_price, NULL) AS specials_new_products_price,
IF(s.status, s.specials_new_products_price, p.products_price) AS final_price,
IF(p.clearance_price < p.products_cost*2.25, p.clearance_price, p.products_cost*2.25) AS sorting_price
FROM products p
LEFT JOIN manufacturers m
using (manufacturers_id)
LEFT JOIN specials s
ON p.products_id = s.products_id
LEFT JOIN products_attributes pa
ON p.products_id = pa.products_id
LEFT JOIN products_options po
ON pa.options_id = po.products_options_id
LEFT JOIN products_options_values pov
ON pa.options_values_id = pov.products_options_values_id ,
products_description pd,
categories c,
products_to_categories p2c
WHERE p.products_status = '1'
AND p.products_id = pd.products_id
AND pd.language_id = '1'
AND p.products_id = p2c.products_id
AND p2c.categories_id = c.categories_id
AND ((
pd.products_name LIKE '%a%'
OR po.products_options_name LIKE '%a%'
OR pov.products_options_values_name LIKE '%a%'
OR pd.products_description LIKE '%a%') )
ORDER BY p.products_id DESC) m
WHERE m.products_id = pa.products_id
AND pa.options_id = 1
AND pa.options_values_id = pov.products_options_values_id
AND pov.language_id = '1'
GROUP BY pov.products_options_values_id
ORDER BY pov.products_options_values_sort_order ASC) q
WHERE q.products_id = ps.products_id
AND ps.products_stock_attributes = concat('1-', pav.products_options_values_id)
AND ps.products_stock_quantity > 0
ORDER BY pav.products_options_values_sort_order ASC
我已经尝试优化它几个小时了,但我可能误读了 EXPLAIN 信息,因为无论我做什么,它似乎都没有使它变得更快,所以我正在向这里的专家寻求帮助。
是什么原因导致它变得这么慢?我应该怎样做才能使它更快?
最佳答案
首先,我使用一致的 JOIN 子句与逗号列出的表清理了查询。接下来,您最里面的查询的顺序显然没有被利用来产生任何好处。如果无法优化 Order by,通常会导致查询出现较大延迟。
SELECT DISTINCT
pav.products_options_values_id,
pav.products_options_values_name,
pav.products_options_values_sort_order
FROM
products_stock ps
JOIN products_options_values pav
ON ps.products_stock_attributes = concat('1-', pav.products_options_values_id)
AND ps.products_stock_quantity > 0
JOIN ( SELECT DISTINCT
pa.products_id,
pov.products_options_values_id,
pov.products_options_values_name,
pa.options_values_price,
pa.price_prefix
FROM
products_attributes pa
JOIN products_options_values pov
ON pa.options_values_id = pov.products_options_values_id
AND pov.language_id = '1'
JOIN ( SELECT DISTINCT
p.products_image,
p.products_quantity,
p.products_status,
p.manufacturers_id,
p.products_id,
p.products_date_added,
p.products_subimage1,
pd.products_name,
p.products_price,
p.products_length,
p.products_width,
p.products_height,
p.products_tax_class_id,
IF(s.status, s.specials_new_products_price, NULL )
AS specials_new_products_price,
IF(s.status, s.specials_new_products_price, p.products_price )
AS final_price,
IF( p.clearance_price < p.products_cost * 2.25, p.clearance_price, p.products_cost * 2.25 )
AS sorting_price
FROM
products p
JOIN products_description pd
ON p.products_id = pd.products_id
AND pd.language_id = '1'
THIS SECTION CAN BE REMOVED JOIN products_to_categories p2c
AND p.products_id = p2c.products_id
JOIN categories c
ON p2c.categories_id = c.categories_id
LEFT JOIN manufacturers m
UP TO THIS LINE ON P.manufacturers_id = m.manufacturers_id
LEFT JOIN specials s
ON p.products_id = s.products_id
LEFT JOIN products_attributes pa
ON p.products_id = pa.products_id
LEFT JOIN products_options po
ON pa.options_id = po.products_options_id
LEFT JOIN products_options_values pov
ON pa.options_values_id = pov.products_options_values_id,
WHERE
p.products_status = '1'
AND ( pd.products_name LIKE '%a%'
OR pd.products_description LIKE '%a%'
OR po.products_options_name LIKE '%a%'
OR pov.products_options_values_name LIKE '%a%' )
ORDER BY
p.products_id DESC) m
WHERE
pa.products_id = m.products_id
AND pa.options_id = 1
GROUP BY
pov.products_options_values_id
ORDER BY
pov.products_options_values_sort_order ASC) q
ON ps.products_id = q.products_id
ORDER BY
pav.products_options_values_sort_order ASC
您已连接到类别表,但未提取任何值或其他条件来返回列。由于没有必要,我已将其删除。之后,我查看了您的 Products_To_Categories 表,除了未在其他任何地方使用并因此被删除的额外联接之外,该表也与查询无关。制造商表也不是必需的,因为您获得的只是制造商的 ID,该 ID 存在于产品表中,因此不需要另一个表
现在讨论索引。我会查看您的表的以下索引
table index
products ( products_status, products_id )
products_description ( products_id, language_id )
products_to_categories ( products_id, categories_id )
categories ( categories_id )
manufacturers ( manufacturers_id )
specials ( products_id, status, specials_new_products_price )
products_attributes ( products_id, options_id, options_values_id )
products_options ( products_options_id, products_options_name )
products_options_values ( products_options_values_id, products_options_values_name )
这只是审核的第一步。现在我想采取额外的步骤来可能删除一层嵌套查询。您的最内部查询会连接到“products_options_values”,但仅适用于语言 ID = 1。为什么不将该列条件添加到内部查询中。然后将 pov.products_options_values_id 和 pov.products_options_values_name 列添加到您的内部查询中,并将语言 ID 添加到内部查询中,您不需要再次重新加入它们。它们可以通过“m”引用。最里面查询的别名。与重新加入。
类似地,最内部的查询对 products_attributes 执行 LEFT JOIN,但在“m”别名查询结果之外仅应用 options_id = 1 的 WHERE 子句。这是没有意义的。为什么不把它也添加到最里面的查询中呢?如果您只查找 Language ID = 1 或 Options_ID = 1 之类的内容,那么消除额外的级别可能会有很大帮助,因为您会限制对所有记录的拉取。
同样,此格式化查询与您的上下文相同,只是结构略有不同,缩进较短,以便更好地查看上下文和嵌套需求。
聊天反馈
select
PQ.*
from
( SELECT STRAIGHT_JOIN DISTINCT
p.products_id,
p.products_image,
p.products_quantity,
p.products_status,
p.manufacturers_id,
p.products_date_added,
p.products_subimage1,
pd.products_name,
p.products_price,
p.products_length,
p.products_width,
p.products_height,
pov.products_options_values_id,
pov.products_options_values_name,
pov.language_id,
pov.products_options_values_sort_order,
p.products_tax_class_id,
IF(s.status, s.specials_new_products_price, NULL)
AS specials_new_products_price,
IF(s.status, s.specials_new_products_price, p.products_price)
AS final_price,
IF(p.clearance_price < p.products_cost*2.25, p.clearance_price, p.products_cost*2.25)
AS sorting_price
FROM
products_attributes pa
JOIN products_options_values pov
ON pa.options_values_id = pov.products_options_values_id
AND pov.language_id = '1'
LEFT JOIN products_options po
ON pa.options_id = po.products_options_id
JOIN products p
ON pa.products_id = p.products_id
AND p.products_status = '1'
JOIN products_description pd
ON p.products_id = pd.products_id
AND pd.language_id = '1'
JOIN products_to_categories p2c
ON p.products_id = p2c.products_id
JOIN categories c
ON p2c.categories_id = c.categories_id
LEFT JOIN manufacturers m
using (manufacturers_id)
LEFT JOIN specials s
ON p.products_id = s.products_id
WHERE
pa.options_id = '1'
AND ( pd.products_name LIKE '%a%'
OR po.products_options_name LIKE '%a%'
OR pov.products_options_values_name LIKE '%a%'
OR pd.products_description LIKE '%a%')) PQ
order by
PQ.Products_id
另外,请注意,我删除了最后的“Order by”子句
关于mysql - MySQL组合查询性能低下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35138208/