mysql - MySQL组合查询性能低下

标签 mysql performance

我有一个带有多个子查询的查询,运行速度非常慢。

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

这是解释结果: http://grabilla.com/06201-5ce9af70-1837-4bf4-b42e-1ecdda39b3b9.png

我已经尝试优化它几个小时了,但我可能误读了 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/

相关文章:

C# - For 循环内部

javascript - 如何在 gtmetrix 中优化 google 分析?

python - 在向量化操作中调用 numpy 函数会影响性能吗?

php - PDO:违反完整性约束(更新表)

php - 在 Laravel 5.1 中选择一个表中不存在于另一表中的所有记录

mysql - 错误代码: 1054

mysql - 如何使用减号运算符编写sql查询以返回缺少相应值的行?

PHP 没有以用户身份加载模块

android - 使用数据绑定(bind)库时需要调用 DataBindingUtil.setContentView() 吗?

mysql - mysql查询中select语句中的计算速度慢