【问题标题】:I have one hell of an SQL query I'd like to optimize. Let's talk about it我有一个要优化的 SQL 查询。让我们来谈谈它
【发布时间】:2012-01-28 06:18:24
【问题描述】:

所以,这里有一个问题可能会让 SQL 专家跳来跳去骂我懒惰,但我很难过。今天早上我们的在线商店崩溃并被烧毁,这里是可疑查询。我整天都在想这个,并没有想出任何天才的优化。我能得到一些帮助吗?有什么关键指标吗?有什么办法可以重组这个?我意识到这就像问墙的另一边有什么,然后给你一个指向另一个方向的望远镜,但我认为这值得一试:

SELECT DISTINCT (SELECT filename FROM (SELECT DISTINCT y.value AS label, x.value AS filename 
                        FROM   `catalog_product_super_link` AS z 
                        INNER JOIN `catalog_product_entity_varchar` AS y 
                        ON z.product_id = y.entity_id 
                        INNER JOIN `catalog_product_entity_varchar` AS x 
                        ON z.product_id = x.entity_id 
                        WHERE  parent_id = (SELECT entity_id 
                                             FROM   `catalog_product_entity`
                                             WHERE  sku LIKE 'F11-ARC-7710%' 
                                             LIMIT  0, 1) 
                        AND y.attribute_id = (SELECT attribute_id 
                                               FROM   `eav_attribute` 
                                               WHERE  attribute_code = 'image_label' 
                                               AND entity_type_id = (SELECT entity_type_id FROM `eav_entity_type` WHERE entity_type_code = 'catalog_product') LIMIT 0, 1) 
                        AND x.attribute_id = (SELECT attribute_id 
                                               FROM   `eav_attribute` 
                                               WHERE  attribute_code = 'image' 
                                               AND entity_type_id = (SELECT entity_type_id FROM `eav_entity_type` WHERE entity_type_code = 'catalog_product'))) AS images WHERE c.value LIKE CONCAT(label,'%') LIMIT 0, 1) AS image,
                        pricing_value, 
                        is_percent, 
                        value_index, 
                        c.value AS label,
                        d.sort_order AS sort_order
                        FROM   `catalog_product_super_attribute_pricing` AS a 
                        INNER JOIN `catalog_product_super_attribute_label` AS b 
                        ON a.product_super_attribute_id = b.product_super_attribute_id 
                        INNER JOIN `eav_attribute_option_value` AS c 
                        ON value_index = c.option_id 
                        INNER JOIN `eav_attribute_option` AS d
                        ON c.option_id = d.option_id 
                        WHERE  a.product_super_attribute_id = (SELECT product_super_attribute_id 
                                                               FROM   `catalog_product_super_attribute` 
                                                               WHERE  product_id = 5928 
                                                               AND attribute_id = 143 LIMIT 0, 1) 

                        UNION ALL

                        SELECT DISTINCT (SELECT filename FROM (SELECT DISTINCT y.value AS label, x.value AS filename 
                                         FROM   `catalog_product_super_link` AS z 
                                         INNER JOIN `catalog_product_entity_varchar` AS y 
                                         ON z.product_id = y.entity_id 
                                         INNER JOIN `catalog_product_entity_varchar` AS x 
                                         ON z.product_id = x.entity_id 
                                         WHERE  parent_id = (SELECT entity_id 
                                                             FROM   `catalog_product_entity`
                                                             WHERE  sku LIKE 'F11-ARC-7710%' 
                                                             LIMIT  0, 1) 
                                         AND y.attribute_id = (SELECT attribute_id 
                                                               FROM   `eav_attribute`
                                                               WHERE  attribute_code = 'image_label' 
                                                               AND entity_type_id = (SELECT entity_type_id FROM `eav_entity_type` WHERE entity_type_code = 'catalog_product') LIMIT 0, 1) 
                                         AND x.attribute_id = (SELECT attribute_id 
                                                               FROM   `eav_attribute` 
                                                               WHERE  attribute_code = 'image' 
                                                               AND entity_type_id = (SELECT entity_type_id FROM `eav_entity_type` WHERE entity_type_code = 'catalog_product'))) AS images
                                                               WHERE label LIKE CONCAT((SELECT value FROM `eav_attribute_option_value` WHERE option_id = c.value LIMIT 0, 1),'%') LIMIT 0, 1) AS image,
                                        0 AS pricing_value, 
                                        0 AS is_percent, 
                                        c.value AS value_index, 
                                        (SELECT value FROM `eav_attribute_option_value` WHERE  option_id = c.value LIMIT  0, 1) AS label,
                                        (SELECT sort_order FROM `eav_attribute_option` WHERE option_id = c.value LIMIT 0, 1) AS sort_order
                        FROM   `catalog_product_entity` AS a 
                        INNER JOIN `cataloginventory_stock_status` AS b 
                        ON a.entity_id = b.product_id 
                        INNER JOIN `catalog_product_entity_int` AS c 
                        ON a.entity_id = c.entity_id 
                        INNER JOIN `cataloginventory_stock_item` AS d 
                        ON a.entity_id = d.product_id 
                        WHERE  c.attribute_id = (SELECT attribute_id 
                                                 FROM   `eav_attribute` 
                                                 WHERE  attribute_code = 'choose_size' 
                                                 AND entity_type_id = (SELECT entity_type_id FROM `eav_entity_type` WHERE entity_type_code = 'catalog_product') LIMIT 0, 1) 
                        AND a.entity_id IN (SELECT DISTINCT product_id 
                                            FROM   `catalog_product_super_link` 
                                            WHERE  parent_id = (SELECT entity_id FROM `catalog_product_entity` WHERE sku LIKE 'F11-ARC-7710%' LIMIT  0, 1)) 
                        AND (b.qty > 0 OR d.manage_stock = 0) 
                        AND (SELECT value 
                             FROM   `eav_attribute_option_value` 
                             WHERE  option_id = c.value 
                             LIMIT  0, 1) NOT IN (SELECT c.value 
                                                  FROM `catalog_product_super_attribute_pricing` AS a
                                                  INNER JOIN `catalog_product_super_attribute_label` AS b ON a.product_super_attribute_id = b.product_super_attribute_id 
                                                  INNER JOIN `eav_attribute_option_value` AS c ON value_index = c.option_id 
                                                  WHERE  a.product_super_attribute_id = (SELECT product_super_attribute_id FROM `catalog_product_super_attribute`
                                                                                 WHERE product_id = 5928 
                                                                                         AND attribute_id = 143))
                        ORDER BY sort_order

提前致谢!

【问题讨论】:

  • 此查询太长且太复杂,无法花时间理解,因此可以对其进行优化。你能给出一个(小!)输入数据、表结构和所需输出的样本吗?

标签: mysql sql database indexing


【解决方案1】:

哦,天哪。

除了 WHERE 子句中每列的索引和 EXPLAIN PLAN 以查看是否有 TABLE SCAN 之外,我没有其他可提供的。

我的经验法则是,七个或更多的 JOINS 会表现不佳。我计算的 INNER JOIN 子句比你的要多。我会对这个查询有严重的保留。可以去规范化吗?视图呢?这对你有帮助吗?你比我更了解你的架构和问题。

【讨论】:

    【解决方案2】:

    快速响应。

    你能在 PLSQL 中做到这一点吗? 你能消除那些子查询吗?

    首先执行它们并存储结果。 假设它们返回一行。

    然后,编写一个较小的查询来传递变量。

    【讨论】:

    • PLSQL 是特定于 Oracle 的。标签上写着 MySQL。但是存储过程的想法是个好主意。
    • 这不是一个坏主意。所有这些子查询都是使这个特定查询在我们的各种开发/登台/实时环境中一直工作的必要条件(我们在 Magento 上,任何在 Magento 上的人都会明白 - ID 会发生变化)。但是将它们分解只会将其变成 7 个查询而不是一个...
    • 在这种情况下,我相信 7 个查询会比一个嵌套查询快。它还应该可以检测您所处的环境并有条件地构建正确的查询。
    • 通过拆分查询和缓存子查询的结果来解决,这样它们只执行一次。
    【解决方案3】:

    我前几天回答的这个问题可能会对你有所帮助:

    How can I optimize this SQL query with nested SELECT's?

    这是为了让嵌套查询更高效。我怀疑如果您分别处理嵌套选择,然后使用结果形成更简单的查询,这将有所帮助。授予的游览查询要复杂得多,因此可能还有更多内容,但希望这是一个开始。

    【讨论】:

      【解决方案4】:

      如果没有更多信息甚至是您的测试平台,这几乎是不可能的......

      但是除了按照其他人的建议运行解释计划和添加索引 - 我看到一些可能可以从那里拉出来以改进的东西:

      例如,您有重复的子选择:像这样:

      (SELECT entity_id 
      FROM   `catalog_product_entity`
      WHERE  sku LIKE 'F11-ARC-7710%' 
      LIMIT  0, 1) 
      

      考虑将这些提取到 FROM 子句的最高级别,然后加入以获得结果。 ONCE 不是很多次。如果您对 3 或 4 个变体执行此操作,您应该会看到改进。

      另一件看起来不太正确的事情是 DISTINCT 嵌套在子选择中非常深...您可能不需要这些,它们可能会增加开销。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-20
        • 2012-09-06
        • 1970-01-01
        • 2018-01-11
        • 2012-02-02
        • 2012-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多