2012-05-03 6 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, не удаляется, то есть некоторый запас и чей продавец не находится в отпуске. Я заказываю по цене (promotion_price, когда есть).

МЕНЬШЕ медленная функция?

Вот вывод 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 

Заранее спасибо за вашу помощь по оптимизации данного запроса.

J

+0

Сначала попробуйте объяснить и вашу схему – zerkms

+1

Начните с добавления индекса к идентификаторам JOIN (если они еще не установлены в PRIMARY). –

+0

В самом деле, он уже установлен НА ОСНОВЕ. Я отредактировал свой вопрос с результатом объяснения – user1372006

ответ

0

Вы не используете ref_delivery_mode таблицы, которые вы включили в с п. Это приводит к возникновению декартова произведения таблиц.

+0

Не могу найти ссылку на таблицу в остальной части запроса. Хорошо подмечено. – Namphibian

+0

Да, я заметил, что за несколько секунд до вашего ответа. Я использовал его, но меня уже нет. Удаление этой строки заставило меня получить что-то вроде 150 мс по запросу. Это хорошее начало, слишком плохо, у меня нет более бесполезных линий! – user1372006

+0

удалите предложение order by из sql, потому что он заставит извлечь всю запись, а затем применить порядок и отобразить только 25 записей. –

Смежные вопросы