2012-05-03 109 views
0

我使用PDO Mysql,並提出要求爲我的數據庫中的產品選擇最便宜的優惠。它工作正常,只有問題是它是緩慢的(對於200個報價(並且仍然只有25個返回))需要幾秒鐘,這比我的目標高很多。優化SQL請求

我不是SQL的專家,所以我在這個問題上尋求你的幫助。這裏是要求,如果需要,我會很樂意提供更多的信息:

SELECT 
      mo.id AS id, 
      mo.stock AS stock, 
      mo.price AS price, 
      mo.promotional_price AS promotional_price, 
      mo.picture_1 AS picture_1, 
      mo.picture_2 AS picture_2, 
      mo.picture_3 AS picture_3, 
      mo.picture_4 AS picture_4, 
      mo.picture_5 AS picture_5, 
      mo.title AS title, 
      mo.description AS description, 
      mo.state AS state, 
      mo.is_new AS is_new, 
      mo.is_original AS is_original, 
      c.name AS name, 
      u.id AS user_id, 
      u.username AS username, 
      u.postal_code AS postal_code, 
      p.name AS country_name, 
      ra.cache_rating_avg AS cache_rating_avg, 
      ra.cache_rating_nb AS cache_rating_nb, 
      GROUP_CONCAT(md.delivery_mode_id SEPARATOR ', ') AS delivery_mode_ids, 
      GROUP_CONCAT(ri.title SEPARATOR ', ') AS delivery_mode_titles 

     FROM 
      mp_offer mo, catalog_product_i18n c, 
      ref_country_i18n p, mp_offer_delivery_mode md, 
      ref_delivery_mode r, 
      ref_delivery_mode_i18n ri, user u 

     LEFT JOIN mp_user_review_rating_i18n ra 
      ON u.id = ra.user_id 

     WHERE (mo.product_id = c.id 
       AND mo.culture = c.culture 
       AND mo.user_id = u.id 
       AND u.country_id = p.id 
       AND mo.id = md.offer_id 
       AND md.delivery_mode_id = ri.id 
       AND mo.culture = ri.culture) 
      AND (mo.culture = 1 
       AND p.culture = 1) 
      AND mo.is_deleted = 0 
      AND mo.product_id = 60 
      AND ((u.holiday_start IS NULL) 
       OR (u.holiday_start = '0000-00-00') 
       OR (u.holiday_end IS NULL) 
       OR (u.holiday_end = '0000-00-00') 
       OR (u.holiday_start > '2012-05-03') 
       OR (u.holiday_end < '2012-05-03')) 
      AND mo.stock > 0 
     GROUP BY mo.id 
     ORDER BY IF (mo.promotional_price IS NULL, 
        mo.price, 
        LEAST(mo.price, mo.promotional_price)) ASC 

     LIMIT 25 OFFSET 0; 

,我要爲有自己的「文化」設置爲1特定產品的報價,不會被刪除,有一些股票賣家不在假期。我按價格訂購(有促銷價格時)。

至少是一個緩慢的功能?

這是EXPLAIN輸出:

id select_type table type possible_keys                  key  key_len ref         rows Extra 
1 SIMPLE  c  const PRIMARY,catalog_product_i18n_product,catalog_product_i18n_culture     PRIMARY 8  const,const       1  "Using temporary; Using filesort" 
1 SIMPLE  mo  ref  PRIMARY,culture,is_deleted,product_id,user_id          culture 4  const        3  "Using where with pushed condition" 
1 SIMPLE  u  eq_ref PRIMARY,user_country                PRIMARY 4  database.mo.user_id     1  "Using where with pushed condition" 
1 SIMPLE  p  eq_ref PRIMARY,ref_country_i18n_culture             PRIMARY 8  database.u.country_id,const   1 
1 SIMPLE  r  ALL  NULL                    NULL NULL NULL        3  "Using join buffer" 
1 SIMPLE  ra  ALL  NULL                    NULL NULL NULL        4 
1 SIMPLE  md  ref  PRIMARY,fk_offer_has_delivery_mode_delivery_mode1,fk_offer_has_delivery_mode_offer1 PRIMARY 4  database.mo.id      2 
1 SIMPLE  ri  eq_ref PRIMARY                    PRIMARY 2  database.md.delivery_mode_id,const 1 

預先感謝您的優化這一請求幫助。

Ĵ

+0

起初 - 顯示解釋和您的模式 – zerkms

+1

開始將索引添加到JOIN ID(如果尚未設置爲PRIMARY)。 –

+0

確實已經設置爲PRIMARY。我編輯我的問題與解釋的輸出 – user1372006

回答

0

你是不是利用你已經從條款列入ref_delivery_mode表。它是得到表結果笛卡爾積的原因。

+0

無法找到對查詢的其餘部分表中的引用。發現得好。 – Namphibian

+0

是的,我注意到你的答覆前幾秒鐘。我正在使用它,但我不再是。刪除該行使我獲得了150毫秒的請求。這是一個好開始,太糟糕了,我沒有更多無用的線路! – user1372006

+0

從sql中刪除order by子句,因爲它將強制獲取所有記錄,然後應用order並僅顯示25條記錄。 –