2015-07-09 3 views
1

Я пытаюсь ускорить запрос mysql, который возвращает много результатов. Идея состоит в том, чтобы показать некоторые результаты, разделенные категориями/неделями и т. Д. Но для их загрузки требуется всегда. Это совершенно непригодно.Ускорить запрос mysql, который возвращает много результатов

Можете ли вы предложить решение? Каковы мои варианты, когда мне приходится иметь дело с такими ситуациями?

SELECT DISTINCT vowao.id_product_attribute, WEEKOFYEAR(vowao.date_purchased) AS week, 
     YEAR(vowao.date_purchased) AS year, 
     (SELECT COUNT(*) 
      FROM ps_view_orders_w_attributes_ordered vowao_s 
      WHERE WEEKOFYEAR(vowao_s.date_purchased) = WEEKOFYEAR(vowao.date_purchased) 
       AND vowao_s.id_product_attribute = vowao.id_product_attribute 
    ) AS amount_sold, 
     (SELECT al.public_name 
      FROM ps_attribute_lang al 
      WHERE al.id_attribute = vpac.id_attribute 
       AND al.id_lang='2' 
    ) AS name, 
     (SELECT al.id_attribute 
      FROM ps_attribute_lang al 
      WHERE al.id_attribute = vpac.id_attribute 
       AND al.id_lang='2' 
    ) AS id_attribute 
    FROM `ps_view_orders_w_attributes_ordered` vowao 
    JOIN `ps_view_product_attribute_combination` vpac 
      ON vpac.id_product_attribute = vowao.id_product_attribute 
    WHERE vowao.id_shop = '".$id_shop."' 
     AND vpac.is_color_group = 1 
     AND WEEKOFYEAR(vowao.date_purchased) IS NOT NULL 
     AND YEAR(vowao.date_purchased) = 2015 
+0

Корреляционный подзапрос будет медленным. Можете ли вы это изменить. – Strawberry

+0

Я попытался переместить эти подзапросы (счет и т. Д.) И поместить их в ловушку. Так что получите результаты и в цикле for get count, в другом для цикла - имя и т. Д. Но я не видел никаких изменений в отношении того, как быстро получаются результаты, к сожалению – shieldcy

+0

№ Нет. Просто некоррелированный подзапрос - infact просто соединение для вторых двух, так как в них нет агрегации. Кроме того, конечно, 'WEEKOFYEAR (date_purchased) НЕ НУЛЛ' - это то же самое, что' date_puchased IS NOT NULL' ?? – Strawberry

ответ

0

Одна вещь, вы можете попробовать это преобразовать коррелированные подзапросы в объединения:

SELECT DISTINCT 
    vowao.id_product_attribute, 
    WEEKOFYEAR(vowao.date_purchased) AS week, 
    YEAR(vowao.date_purchased) AS year, 
    amounts_sold.total, 
    attr_names.id_attribute, 
    attr_names.public_name AS name, 
FROM `ps_view_orders_w_attributes_ordered` vowao 
JOIN `ps_view_product_attribute_combination` vpac ON vpac.id_product_attribute = vowao.id_product_attribute 
LEFT JOIN (
    SELECT WEEKOFYEAR(vowao_s.date_purchased) AS s_week, vowao_s.id_product_attribute AS s_attr, COUNT(*) AS total 
    FROM ps_view_orders_w_attributes_ordered vowao_s 
    GROUP BY WEEKOFYEAR(vowao_s.date_purchased), vowao_s.id_product_attribute 
) amounts_sold ON amounts_sold.s_week = WEEKOFYEAR(vowao.date_purchased) AND amounts_sold.s_attr = vowao.id_product_attribute 
LEFT JOIN (
    SELECT al.id_attribute, al.public_name 
    FROM ps_attribute_lang al 
    WHERE al.id_lang='2' 
) attr_names ON al.id_attribute = vpac.id_attribute 
WHERE vowao.id_shop = '".$id_shop."' 
    AND vpac.is_color_group = 1 
    AND WEEKOFYEAR(vowao.date_purchased) IS NOT NULL 
    AND YEAR(vowao.date_purchased) = 2015 

Для лучшего/больше помощи, показывают результаты использования EXPLAIN по Вашему запросу. Вы также можете создать SQL-скрипт с соответствующей схемой и примерными данными, чтобы помочь помощникам.

+1

Если это будет быстрее, я распечатаю его и съеду. – Strawberry

+0

Я думаю, что скорость более или менее одинаковая. Но спасибо anw :) – shieldcy

2

Игнорирование агрегации часть сейчас, что-то вроде этого будет быстрее ...

SELECT DISTINCT v.id_product_attribute 
       , DATE_FORMAT(v.date_purchased,'%v-%x') yearweek 
       , al.public_name 
       , al.id_attribute 
      FROM ps_view_orders_w_attributes_ordered v 
      JOIN ps_view_product_attribute_combination vpac 
       ON vpac.id_product_attribute = v.id_product_attribute 
      JOIN ps_attribute_lang al 
       ON al.id_lang = vpac.id_attribute 
      WHERE v.id_shop = '$id_shop' 
      AND vpac.is_color_group = 1 
      AND v.date_purchased BETWEEN '2015-01-01' AND '2015-12-31' 
      AND v.date_purchased IS NOT NULL 
      AND al.id_attribute = 2; 

Следующим шагом будет провести обзор EXPLAIN, и добавить индексы в зависимости от обстоятельств.

+0

спасибо за это. Мне нужно будет протестировать его – shieldcy

1

Я взял трещину. Здесь были мои цели:

  1. Нет коррелированные подзапросы
  2. Нет DISTINCT (вероятно, что замедлилось Вас наиболее)
  3. Нет ненужных формул в ограничениях
  4. Все стандартные SQL (потому что я не то, что ! знакомы с синтаксисом MySQL)

Вот запрос:

SELECT 
    vowao.id_product_attribute, 
    WEEKOFYEAR(vowao.date_purchased) AS week, 
    YEAR(vowao.date_purchased) AS year, 
    amount_group.amount_sold, 
    al.public_name AS name, 
    al.id_attribute AS id_attribute 
FROM 
    `ps_view_orders_w_attributes_ordered` vowao 
JOIN 
    `ps_view_product_attribute_combination` vpac 
    ON 
    vpac.id_product_attribute = vowao.id_product_attribute 
LEFT JOIN 
    ps_attribute_lang al 
    ON 
    al.id_attribute = vpac.id_attribute 
    AND 
    al.id_lang='2' 
LEFT JOIN 
    (SELECT 
     WEEKOFYEAR(date_purchased) as week_of_year, 
     id_product_attribute, 
     COUNT(*) as amount_sold 
    FROM 
     ps_view_orders_w_attributes_ordered 
    GROUP BY 
     WEEKOFYEAR(date_purchased), 
     id_product_attribute 
    ) amount_group 
    ON 
    WEEKOFYEAR(vowao.date_purchased) = amount_group.week_of_year 
    AND 
    vowao.id_product_attribute = amount_group.id_product_attribute 
WHERE 
    vowao.id_shop = '".$id_shop."' 
    AND 
    vpac.is_color_group = 1 
    AND 
    vowao.date_purchased IS NOT NULL 
    AND 
    YEAR(vowao.date_purchased) = 2015 
GROUP BY 
    vowao.id_product_attribute, 
    WEEKOFYEAR(vowao.date_purchased), 
    YEAR(vowao.date_purchased), 
    al.public_name, 
    al.id_attribute 
+0

Это все еще очень медленно :(Но спасибо за предложения, помните об этом и попытайтесь улучшить sql-запрос вообще – shieldcy

+0

Если все эти альтернативы медленны, тогда вам, скорее всего, не хватает всех важные индексы, которые нужны вашим таблицам. Возможно, если бы вы могли предоставить полную схему для этих таблиц, мы могли бы помочь больше. В противном случае вы сами будете использовать 'EXPLAIN'. –

0

INDEX(id_lang, id_attribute)al потребности (или обратный порядок)

ключ-значение (EAV) схемы, как известно, неуклюже и неэффективно.

AND YEAR(vowao.date_purchased) = 2015 скрывает потенциально проиндексированный столбец внутри функции, тем самым исключая возможность использования индекса. Вместо этого сделать

AND vowao.date_purchased >= '2015-01-01 
AND vowao.date_purchased < '2015-01-01 + INTERVAL 1 YEAR 

Избавиться от этого, так как выше запрос не будет для NULL:

AND WEEKOFYEAR(vowao.date_purchased) IS NOT NULL 

После того, как вы сделали те, добавить

INDEX(id_shop, date_purchased) 

Просьба SHOW CREATE TABLE для каждого таблицу, поэтому нам не нужно будет догадываться, что не так.

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