我有多个子查询的查询,运行速度很慢。
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信息,因为无论我做什么,它似乎都不会让它更快,所以我在这里寻求专家的帮助。
导致它变得如此缓慢的原因是什么?我应该怎样做才能使它变得快速?
答案 0 :(得分:1)
首先,我使用一致的JOIN子句与逗号列出的表清理查询。接下来,您最内部的查询有一个顺序,显然没有被用于任何好处。如果无法优化,则排序依据会导致查询出现大的延迟。
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,它存在于产品表中,因此不需要另外的表
现在开始索引。我会查看表的以下索引
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 )
这只是评论的第一步。现在我想再花一步来删除一层嵌套查询。您的INNER-MOST查询会加入&#34; products_options_values&#34;但仅适用于Language ID = 1.为什么不将该列标准添加到内部查询中。然后将pov.products_options_values_id和pov.products_options_values_name列添加到内部查询和内部查询的语言ID,您不需要再次重新加入它们。它们可以通过&#34; m。&#34;最内层查询的别名。 vs the rejoin。
类似地,您的最内部查询对products_attributes进行LEFT JOIN,但在&#34; m&#34;之外。别名查询结果仅应用options_id = 1的WHERE子句。这没有意义。为什么不直接添加到最内层的查询。如果你只是在寻找语言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
另外,请注意,我删除了最终的&#34; Order by&#34;条款