加速返回许多结果的mysql查询

时间:2015-07-09 12:45:22

标签: mysql database query-optimization

我正在尝试加速返回大量结果的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

4 个答案:

答案 0 :(得分: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,并根据需要添加索引。

答案 1 :(得分:1)

我对它采取了一个裂缝。这是我的目标:

  1. 没有相关的子查询
  2. DISTINCT(可能会减慢你的速度)
  3. 约束中没有不必要的公式
  4. 所有标准SQL(因为我并不熟悉MySQL语法!)
  5. 以下是查询:

    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
    

答案 2 :(得分: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 Fiddle以帮助帮助程序。

答案 3 :(得分:0)

al需要INDEX(id_lang, id_attribute)(或相反的顺序)

键值(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,这样我们就不必猜测出错了什么。