2016-01-23 4 views
0

У меня есть 2 запроса, которые выполняются очень быстро при запуске отдельно, но при объединении с использованием одного из них в качестве подзапроса производительность резко ухудшается.Медленная производительность комбинированных быстрых запросов MySQL

БЫСТРО QUERY I:

SELECT DISTINCT p.products_image, 
       p.products_subimage1, 
       pd.products_name, 
       p.products_quantity, 
       p.products_model, 
       p.products_ordered, 
       p.products_id, 
       p.products_price, 
       p.products_weight, 
       p.products_length, 
       p.products_width, 
       p.products_height, 
       p.products_tax_class_id, 
       p.products_status, 
       IF(s.status, s.specials_new_products_price, NULL)    AS 
       specials_new_products_price, 
       IF(s.status, s.specials_new_products_price, p.products_price) AS 
       final_price 
FROM products p 
     LEFT JOIN specials s 
       ON p.products_id = s.products_id 
     LEFT JOIN products_to_categories p2c 
       ON p.products_id = p2c.products_id 
     LEFT JOIN products_description pd 
       ON p.products_id = pd.products_id 

     LEFT JOIN products_attributes pa 
       ON p.products_id = pa.products_id 
     LEFT JOIN (SELECT `products_id`, 
       `products_stock_attributes`, 
       `products_stock_quantity` 
     FROM products_stock 
     WHERE `products_stock_quantity` > 0) t 
     ON t.products_id = p.products_id 
     WHERE t.products_stock_attributes IN ('1-31', '1-25', '1-18', '1-7') 
     AND p.products_status = '1' 
     AND Date_sub(Curdate(), INTERVAL 30 day) >= p.products_date_added 
     AND pa.options_values_id IN (31, 25, 18, 7) 
GROUP BY p.products_id 
HAVING Count(DISTINCT pa.options_values_id) = 4 
     AND Count(DISTINCT t.products_stock_attributes) = 4 

БЫСТРО QUERY II:

SELECT sul2.* 
FROM stock_update_log sul2 
INNER JOIN (SELECT products_id, 
    Max(date_time) AS maxDateTime 
FROM stock_update_log 
WHERE stock_qty_change > 1 
AND id > 154700 
    AND Date_sub(Curdate(), INTERVAL 360 day)<= From_unixtime(date_time) 
GROUP BY products_id)gsul 
     ON sul2.products_id = gsul.products_id 
AND sul2.date_time = gsul.maxdatetime 

КОМБИНИРОВАННЫЕ ЗАПРОСЫ (ОЧЕНЬ МЕДЛЕННО):

SELECT DISTINCT p.products_image, 
       p.products_subimage1, 
       pd.products_name, 
       p.products_quantity, 
       p.products_model, 
       p.products_ordered, 
       p.products_id, 
       p.products_price, 
       sul.date_time, 
       p.products_weight, 
       p.products_length, 
       p.products_width, 
       p.products_height, 
       p.products_tax_class_id, 
       p.products_status, 
       IF(s.status, s.specials_new_products_price, NULL)    AS 
       specials_new_products_price, 
       IF(s.status, s.specials_new_products_price, p.products_price) AS 
       final_price 
FROM products p 
     LEFT JOIN specials s 
       ON p.products_id = s.products_id 
     LEFT JOIN products_to_categories p2c 
       ON p.products_id = p2c.products_id 
     LEFT JOIN products_description pd 
       ON p.products_id = pd.products_id 
     LEFT JOIN (SELECT sul2.* 
        FROM stock_update_log sul2 
         INNER JOIN (SELECT products_id, 
              Max(date_time) AS maxDateTime 
            FROM stock_update_log 
            WHERE stock_qty_change > 1 
              AND id > 154700 
              AND Date_sub(Curdate(), 
               INTERVAL 360 day) 
               <= 
               From_unixtime(date_time) 
            GROUP BY products_id)gsul 
           ON sul2.products_id = gsul.products_id 
            AND sul2.date_time = gsul.maxdatetime) sul 
       ON p.products_id = sul.products_id 
     LEFT JOIN products_attributes pa 
       ON p.products_id = pa.products_id 
     LEFT JOIN (SELECT `products_id`, 
       `products_stock_attributes`, 
       `products_stock_quantity` 
     FROM products_stock 
     WHERE `products_stock_quantity` > 0) t 
     ON t.products_id = p.products_id 
     WHERE t.products_stock_attributes IN ('1-31', '1-25', '1-18', '1-7') 
     AND p.products_status = '1' 
     AND Date_sub(Curdate(), INTERVAL 360 day) <= From_unixtime(sul.date_time) 
     AND Date_sub(Curdate(), INTERVAL 30 day) >= p.products_date_added 
     AND sul.id > 154700 
     AND sul.stock_qty_change > 1 
     AND pa.options_values_id IN (31, 25, 18, 7) 
GROUP BY p.products_id 
HAVING Count(DISTINCT pa.options_values_id) = 4 
     AND Count(DISTINCT t.products_stock_attributes) = 4 
ORDER BY sul.date_time DESC 

EXPLAIN комбинированных запросов результат: EXPLAIN of combined quries result

Я пытался в течение нескольких часов, чтобы выяснить, почему это получить так медленно, комбинируя их таким образом и пытался переписать комбинированный запрос не дали никаких результатов, поэтому я тянуться помощь от экспертов здесь.

Что может быть причиной его становления настолько медленным, и что я должен сделать, чтобы сделать его быстрым?

ответ

1

Query II чувствует, что у него миллион строк; итоговая таблица tmp не имеет индекса; и он скрыт за LEFT JOIN. Тем не менее оптимизатор кажется достаточно умным, чтобы начать с этого беспорядка и предоставить 7904 строк для совместного запроса.

Вы можете избежать LEFT?

Затем код прогрессирует, но в конечном итоге должен проверить все эти строки на 18057 строк из сканирования таблицы. Опять же Оптимизатор делает умную вещь, используя «буфер соединения». Тем не менее, 7904 * 923 * 18057 - это много строк, на которые нужно смотреть.

Это, кажется, злой часть:

LEFT JOIN 
    (SELECT `products_id`, 
       `products_stock_attributes`, 
       `products_stock_quantity` 
     FROM products_stock 
     WHERE `products_stock_quantity` > 0 
    ) t 
    ON t.products_id = p.products_id 

    WHERE t.products_stock_attributes IN ('1-31', '1-25', '1-18', '1-7') 

Все они кажутся красными флагами: (?)

  • Ненужные LEFT;
  • «где атрибуты в ...» вне подзапроса, когда они могут быть внутри;
  • Возможно, вы сфотографировали HAVING Count(DISTINCT t.products_stock_attributes) = 4 в подзапрос.
+0

Да, перемещая 'WHERE t.products_stock_attributes IN' и' HAVING Count (DISTINCT t.products_stock_attributes) = 4' в этот подзапрос, решила проблему. Большое спасибо!! :) – CreativeMind

1

Вы занимаетесь объединением более 7 таблиц, которые обязательно будут очень медленными. Я бы рекомендовал избежать объединения более трех таблиц.

Вы пробовали сами выполнить два вопроса, а затем объединить их результаты?

+0

Продвижение для попытки помочь мне. Спасибо. :) – CreativeMind

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