第三个嵌套的Mysql选择查询导致巨大的性能问题

时间:2014-02-04 01:30:13

标签: mysql sql magento

我正在Magento数据库上进行一些SQL查询以获取一些客户订单信息。

我想要运行的查询如下

SELECT * FROM catalog_category_product
WHERE product_id IN (
                    SELECT product_id FROM sales_flat_order_item
                    WHERE product_type = 'configurable'
                    AND order_id IN ( 
                                        SELECT entity_id FROM sales_flat_order
                                        WHERE customer_id = 12657
                                        AND state = 'complete')
)

基本上这是做什么的,是为客户获取所有entity_id(订单ID),将这些插入到从这些订单中获取product_ids的查询中,然后从那里返回这些产品的category_ids。

当我运行此命令时,查询需要很长时间才能运行,我在等待2分钟+运行后将其杀死。

如果我将第三个嵌套查询替换为数组中的硬编码校验,那么查询将在大约5秒后返回:

SELECT * FROM catalog_category_product
WHERE product_id IN (
                    SELECT product_id FROM sales_flat_order_item
                    WHERE product_type = 'configurable'
                    AND order_id IN ( 
13446, 13579, 13840, 14361, 14383, 14497, 14798, 16357, 17299, 17332, 18338, 18542, 18755, 19786, 20006
)
)

我对MySQL性能不太熟悉,所以我不确定自己是否会突破界限。

如果我运行第三个嵌套查询,它将在不到一秒的时间内返回。

SELECT entity_id FROM sales_flat_order
                                        WHERE customer_id = 12657
                                        AND state = 'complete'

如果我获取这些值并将它们放入第二个嵌套查询“IN”中,则顶部查询将在~5秒内返回。

为什么组合它会导致爆发?

2 个答案:

答案 0 :(得分:2)

只有在绝对必要时才应使用子查询,因为它们必然(或几乎总是)会降低性能。在这种情况下,您可以使用以下查询获得相同的结果,我猜测性能将得到很大改善:

SELECT ccp.*
FROM catalog_category_product ccp
    INNER JOIN sales_flat_order_item sfoi ON ccp.product_id = sfoi.product_id
    INNER JOIN sales_flat_order sfo ON sfoi.order_id = sfo.entity_id
WHERE sfoi.product_type = 'configurable'
    AND sfo.customer_id = 12657
    AND sfo.state = 'complete';

答案 1 :(得分:2)

我不熟悉数据库结构,但尝试更改为使用连接而不是嵌套的in语句。这假设sales_flat_ordersales_flat_order_item表之间存在一对多关系,sales_flat_order_itemcatalog_category_product表之间存在一对一关系。

SELECT DISTINCT ccp.* --this will return all columns for the catalog_category_product table
--Or if you only wanted the "category_ids for those products", then use this instead: SELECT DISTINCT ccp.category_id  
FROM sales_flat_order sfo
INNER JOIN sales_flat_order_item sfoi ON sfo.entity_id = sfoi.order_id 
INNER JOIN catalog_category_product ccp ON ccp.product_id = sfoi.product_id
WHERE sfo.customer_id = 12657
AND sfo.state = 'complete'
AND sfoi.product_type = 'configurable'