将Prestashop实例从MySQL迁移到MariaDB后,过滤后的搜索查询变慢。以下是这种慢查询的示例。
SELECT
fl.name feature_name,
fp.id_feature,
fv.id_feature_value,
fvl.value,
COUNT(DISTINCT p.id_product) nbr,
lifl.url_name name_url_name,
lifl.meta_title name_meta_title,
lifvl.url_name value_url_name,
lifvl.meta_title value_meta_title,
psi.price_min,
psi.price_max,
m.name
FROM
ps_feature_product fp
INNER JOIN
ps_product p
ON
(p.id_product = fp.id_product)
LEFT JOIN
ps_feature_lang fl
ON
(
fl.id_feature = fp.id_feature AND fl.id_lang = 2
)
INNER JOIN
ps_feature_value fv
ON
(
fv.id_feature_value = fp.id_feature_value AND(
fv.custom IS NULL OR fv.custom = 0
)
)
LEFT JOIN
ps_feature_value_lang fvl
ON
(
fvl.id_feature_value = fp.id_feature_value AND fvl.id_lang = 2
)
LEFT JOIN
ps_layered_indexable_feature_lang_value lifl
ON
(
lifl.id_feature = fp.id_feature AND lifl.id_lang = 2
)
LEFT JOIN
ps_layered_indexable_feature_value_lang_value lifvl
ON
(
lifvl.id_feature_value = fp.id_feature_value AND lifvl.id_lang = 2
)
INNER JOIN
ps_product_shop product_shop
ON
(
product_shop.id_product = p.id_product AND product_shop.id_shop = 1
)
INNER JOIN
`ps_layered_price_index` psi
ON
(
psi.id_product = p.id_product AND psi.id_currency = 2 AND psi.id_shop = 1
)
LEFT JOIN
`ps_manufacturer` m
ON
(
m.id_manufacturer = p.id_manufacturer
)
WHERE
product_shop.`active` = 1 AND product_shop.`visibility` IN("both", "catalog") AND fp.id_feature = 9 AND p.id_product IN(
SELECT
id_product
FROM
ps_category_product cp
INNER JOIN
ps_category c
ON
(
c.id_category = cp.id_category AND c.id_category = 13 AND c.active = 1
)
) AND p.id_product IN(
SELECT
id_product
FROM
ps_feature_product fp
WHERE
fp.`id_feature_value` = 39
) AND p.id_product IN(
SELECT
id_product
FROM
ps_feature_product fp
WHERE
fp.`id_feature_value` = 18
) AND p.id_product IN(
SELECT
id_product
FROM
ps_feature_product fp
WHERE
fp.`id_feature_value` = 13
) AND p.id_product IN(
SELECT
id_product
FROM
ps_feature_product fp
WHERE
fp.`id_feature_value` = 44
) AND p.id_product IN(
SELECT
id_product
FROM
ps_feature_product fp
WHERE
fp.`id_feature_value` = 3186
)
GROUP BY
fv.id_feature_value
ORDER BY
fv.position
有趣的是,如果WHERE子句中的多个(几乎相同的)子查询中的一个被删除,它会快得多(4s vs 0.4s)。
... AND
/*
-- removing any of the six product filters makes
-- the query a lot faster
p.id_product IN(
SELECT
id_product
FROM
ps_feature_product fp
WHERE
fp.`id_feature_value` = 18
)
*/
AND ...
这是此查询的EXPLAIN输出(没有修改)。
有什么明显的东西需要以某种方式改变吗?所有表格都已经OPTIMIZEd没有任何改进。
答案 0 :(得分:2)
你有以下几种:
AND p.id_product IN (
SELECT id_product
FROM ps_feature_product fp
WHERE fp.`id_feature_value` = 39 )
可以变成这个
AND EXISTS ( SELECT * FROM ps_feature_product
WHERE id_product = p.id_product
AND id_feature_value = 39 )
IN ( SELECT ... )
优化不佳。
请务必拥有INDEX(id_product, id_feature_value)
。
MySQL和MariaDB之间性能差异的原因是几个优化改进差异大约为5.6。它们涉及与你正在做的事情有关的事情。
像
这样的事情 LEFT JOIN ps_layered_indexable_feature_value_lang_value lifvl
ON ( lifvl.id_feature_value = fp.id_feature_value
AND lifvl.id_lang = 2
需要复合INDEX(id_feature_value, id_lang)
(按任意顺序)。但我可以从EXPLAIN
中猜出你有这样的情况。
请为每个表提供SHOW CREATE TABLE
,可能会有更多建议。
我无法解决您的具体问题,因为我不知道EXPLAIN
的哪一行与删除的条款相对应。