2013-05-30 109 views
1

加入順序我有以下查詢:優化通過查詢

SELECT `p_products`.`id`, `p_products`.`name`, `p_products`.`date`, 
     `p_products`.`img`, `p_products`.`safe_name`, `p_products`.`sku`, 
     `p_products`.`productstatusid`, `op`.`quantity` 
FROM `p_products` 
INNER JOIN `p_product_p_category` 
     ON `p_products`.`id` = `p_product_p_category`.`p_product_id` 
LEFT JOIN (SELECT `p_product_id`,`order_date`,SUM(`product_quantity`) as quantity 
      FROM `p_orderedproducts` 
      WHERE `order_date`>='2013-03-01 16:51:17' 
      GROUP BY `p_product_id`) AS op 
     ON `p_products`.`id` = `op`.`p_product_id` 
WHERE `p_product_p_category`.`p_category_id` IN ('15','23','32') 
    AND `p_products`.`active` = '1' 
GROUP BY `p_products`.`id` 
ORDER BY `date` DESC 

解釋說:

 
id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY p_product_p_category ref p_product_id,p_category_id,p_product_id_2 p_category_id 4 const 8239 Using temporary; Using filesort 
1 PRIMARY p_products eq_ref PRIMARY PRIMARY 4 pdev.p_product_p_category.p_product_id 1 Using where 
1 PRIMARY ALL NULL NULL NULL NULL 78 
2 DERIVED p_orderedproducts index order_date p_product_id 4 NULL 201 Using where 

而且我有一些列的包括p_products.date指標。

問題是在多個類別中有超過5000個產品時的速度。 60000產品需要> 1秒。有什麼辦法可以加快速度嗎?

如果我刪除左這也成立加入這種情況下,結果是:

 
id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE p_product_p_category index p_product_id,p_category_id,p_product_id_2 p_product_id_2 8 NULL 91167 Using where; Using index; Using temporary; Using filesort 
1 SIMPLE p_products eq_ref PRIMARY PRIMARY 4 pdev.p_product_p_category.p_product_id 1 Using where 

的intermediatate表p_product_p_category有兩個p_product_id索引和藏漢p_category_id作爲同時具有組合索引。

試圖越智的建議,並結束了:

 
id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY ALL NULL NULL NULL NULL 62087 Using temporary; Using filesort 
1 PRIMARY nr1media_products eq_ref PRIMARY PRIMARY 4 cats.nr1media_product_id 1 Using where 
2 DERIVED nr1media_product_nr1media_category range nr1media_category_id nr1media_category_id 4 NULL 62066 Using where 

我想我可以簡化問題我怎麼能加入我的產品的類別中間表來獲取所有獨特的產品所選類別排序日期。

編輯:

這使我在類別中的所有獨特的產品,而無需使用臨時表的排序或分組:

SELECT 
    `p_products`.`id`, 
    `p_products`.`name`, 
    `p_products`.`img`, 
    `p_products`.`safe_name`, 
    `p_products`.`sku`, 
    `p_products`.`productstatusid` 
FROM 
    p_products 
WHERE 
    EXISTS (
     SELECT 
      1 
     FROM 
      p_product_p_category 
     WHERE 
      p_product_p_category.p_product_id = p_products.id 
     AND p_category_id IN ('15', '23', '32') 
    ) 
AND p_products.active = 1 
ORDER BY 
    `date` DESC 

以上查詢是非常快的,速度更快那麼連接使用GROUP BY順序由(0.04 VS 0.7秒),雖然我不明白爲什麼它可以做這個查詢沒有臨時表。

我想我需要爲訂購的產品加入找到另一個解決方案,它仍然減慢查詢下降到> 1秒。可以讓cron更新每晚銷售一次的產品的排名並將該信息保存到p_products表中。

除非有人有一個明確的解決方案......

回答

2

要加入每一種類型類別的產品 - 只有這樣它就會按類別ID

嘗試過濾儘快爲例如限制查詢而不是

INNER JOIN `p_product_p_category` 

INNER JOIN (SELECT * FROM `p_product_p_category` WHERE `p_category_id` IN ('15','23','32')) 

,這樣你就可以直接從begining

+0

執行時間實際上是更大的使用子查詢,我會更新後的解釋使用您的建議。 –

+0

@Ochi:很好的建議。 – ankurtr

2

一個可能的解決辦法是刪除派生表工作的產品更小的子集,只是做單分組:

Select P.id, P.name, P.date 
    , P.img, P.safe_name, P.sku 
    , P.productstatusid 
    , Sum(OP.product_quantity) As quantity 
From p_products As P 
    Join p_product_p_category As CAT 
     On p_products.id = CAT.p_product_id 

    Left Join p_orderedproducts As OP 
     On OP.p_product_id = P.id 
      And OP.order_date >= '2013-03-01 16:51:17' 

Where CAT.p_category_id In ('15','23','32') 
    And P.active = '1' 
Group By P.id, P.name, P.date 
    , P.img, P.safe_name, P.sku 
    , P.productstatusid 
Order By P.date Desc 
+0

謝謝托馬斯,幫助颳了一些時間!仍然不是我想要它的地方,所以我現在要實施Ochi的建議。 –

+0

+1用於刪除派生表。 – ankurtr