mysql - 如何优化 prestashop 类别随机获取产品
问题描述
这是prestashop 1.7 版本分类获取产品查询。如果使用随机,它很慢,如何优化它?
选择 cp.id_category, p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) AS 数量, IFNULL(product_attribute_shop.id_product_attribute, 0) 作为 id_product_attribute, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, pl.`描述`, pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`名称`, image_shop.`id_image` id_image, il.`legend` 作为图例, m.`name` AS 制造商名称, cl.`name` AS category_default, 日期差异( product_shop.`date_add`, DATE_SUB("2019-11-30 00:00:00", INTERVAL 7 DAY )) > 0 AS new, product_shop.price AS orderprice 从 `ps_category_product` cp 左连接`ps_product` p ON p.`id_product` = cp.`id_product` 内部加入 ps_product_shop product_shop ON (product_shop.id_product = p.id_product AND product_shop.id_shop = 1) 左加入`ps_product_attribute_shop` product_attribute_shop ON(p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop = 1) 左加入 ps_stock_available 库存(stock.id_product = `p`.id_product AND stock.id_product_attribute = 0 AND stock.id_shop = 1 AND stock.id_shop_group = 0) 左连接`ps_category_lang` cl ON (product_shop.`id_category_default` = cl.`id_category` AND cl.`id_lang` = 11 AND cl.id_shop = 1) 左连接`ps_product_lang` pl ON(p.`id_product` = pl.`id_product` AND pl.`id_lang` = 11 AND pl.id_shop = 1) 左加入`ps_image_shop` image_shop ON(image_shop.`id_product` = p.`id_product` AND image_shop.cover = 1 AND image_shop.id_shop = 1) 左加入`ps_image_lang` il ON(image_shop.`id_image` = il.`id_image` AND il.`id_lang` = 11) 左连接`ps_manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer` 在哪里 product_shop.`id_shop` = 1 AND cp.`id_category` = 12 AND product_shop.`active` = 1 AND product_shop.`visibility` IN ("both", "catalog" ) 订购方式 兰德() 限制 50
解决方案
请提供SHOW CREATE TABLE
每张桌子。同时, ...
让我们从优化连接开始。
LEFT JOIN `ps_product_lang` pl ON ( p.`id_product` = pl.`id_product`
AND pl.`id_lang` = 11
AND pl.id_shop = 1 )
这需要INDEX(id_product, id_lang, id_shop)
(列可以按任何顺序排列。)
LEFT
除非您确实需要从右侧表中获取不存在的行作为 NULL,否则不要使用它。尤其是,
LEFT JOIN `ps_product` p
可能会妨碍优化。
WHERE product_shop.`id_shop` = 1
AND product_shop.`active` = 1
AND product_shop.`visibility` IN ( "both", "catalog" )
可能会从这些索引中受益
INDEX(id_shop, active, visibility, id_product)
INDEX(id_product, id_shop, active, visibility)
product_category
需要
INDEX(id_category, id_product) -- in this order.
一般多对多映射表需要遵循这里的提示:http: //mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
该查询具有“explode-implode”综合症。这是它首先执行的地方JOINs
,收集大量数据,然后丢弃大部分数据,在您的情况下,由于LIMIT 10
. 它可能可以通过将查询从里到外来解决。通用 ID 是从获取所需 10 行的派生表开始,然后进入另一个表以获取所需列的其余部分。这种“到达”需要只发生 10 次,而不是JOINs
当前需要的次数。
SELECT ...
FROM ( SELECT <<primary key columns from cp, p, and product_shop>>
FROM cp
JOIN p ON ...
JOIN product_shop ON ...
ORDER BY RAND()
LIMIT 10 ) AS x
JOIN <<p, product_shop ON their PKs>> -- to get p.*, product_shop.*>>
[LEFT] JOIN << each of the other tables>> -- to get the other tables
您应该首先测试子查询(“派生”表),以验证它是否明显比原始查询快。
推荐阅读
- audio - 音频编解码器的这种变化会导致明显的差异吗?
- javascript - 在 vuejs 中使用突变过滤?
- ruby-on-rails - 与 SwitchPoint 并行有时在 Rails 上没有连接错误
- swift - 如何在没有样板的情况下从超类访问内部对象的属性
- python - tensorflow 2.0:tf.GradientTape().gradient() 返回无
- android - 有没有办法从 MainActivity 访问 Dialog 对象?
- python - 如何使用 numpy 重写
- javascript - 将内联 javascript 转换为外部文件
- mysql - 如何在 mysql 5.7 中使用 sum over partition (withhout window function)
- php - 如何在 PHP 中的新 Amazon Alexa.com Rank API 中设置凭据?