首页 > 解决方案 > 如何优化 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

标签: mysqloptimizationrandomprestashop

解决方案


请提供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

您应该首先测试子查询(“派生”表),以验证它是否明显比原始查询快。


推荐阅读