2012-05-03 3 views
0

필자는 PDO Mysql을 사용하여 데이터베이스에서 가장 저렴한 제품을 선택하도록 요청했습니다. 그것은 잘 작동합니다, 문제는 단지 느린 것입니다 (200 개 제안 (그리고 여전히 25 개로 돌아 가기 위해)). 그것은 거의 1 초가 걸리고, 이것은 제가 목표로하는 것보다 훨씬 큽니다.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로 설정 그들의 "문화"가 특정 제품에 대한 제안을 가지고, 어떤 주식을 가지고이 삭제되지 않습니다 그의 판매자는 휴일이 아닙니다. 나는 가격으로 주문한다.

저조한 기능입니까? 이 요청을 최적화에 대한 당신의 도움에 미리

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 

감사 : 여기

는 EXPLAIN의 출력입니다.

당신이 절에서 포함했다 ref_delivery_mode 테이블의 사용을하지 않는

+0

처음에 설명과 스키마 표시 – zerkms

+1

JOIN ID에 색인을 추가하는 것으로 시작하십시오 (아직 PRIMARY로 설정되지 않은 경우). –

+0

실제로 이미 PRIMARY로 설정되어 있습니다. 난 내 질문을 편집 – user1372006

답변

0

J. 그것은 테이블 결과의 데카르트 제품의 원인을 얻고 있습니다.

+0

의 설명과 함께 편집 쿼리의 나머지 부분에 테이블을 참조하십시오. 잘 보였다. – Namphibian

+0

예 답장 받기 몇 초 전에 나타났습니다. 나는 그것을 사용하고 있었지만 더 이상은 아니다. 그 행을 삭제하면 요청에 대해 150ms와 같은 것을 얻을 수있었습니다. 좋은 시작 이네, 나쁘지 않은 라인이 더 없어! – user1372006

+0

sql에서 order by 절을 제거하십시오. 모든 레코드를 페치하고 순서를 적용하여 25 개의 레코드 만 표시해야하기 때문입니다. –