繁体   English   中英

需要帮助优化复杂的MySQL查询

[英]Need Help optimizing a complex MySQL query

我在下面有这个查询。 涉及4个主要表:tblOrder,tblItems,tblOrder_archive,tblItem_archive。 几个月后,订单和项目将移至表的存档版本,以免减慢主表查询的速度。 (销售和流量确实很高)。 因此,要获取销售数字,我从每组表中选择所需的文件(存档和非存档)..将它们合并..对联合进行分组..然后对结果进行一些数学运算。

问题在于,如果有大量行(排序时间跨度),查询将花费很长时间运行,从而超时。 我添加了所有我能想到的键,但运行起来仍然非常慢。

我还能做些什么来加快运行速度吗? 我可以改写吗? 我可以使用不同的索引吗?

还是我应该编写一个脚本,该脚本首先从每个表集中获取数据,然后php脚本中的数学将它们组合起来?

谢谢您的帮助。

SELECT
  description_invoice
, supplier
, type
, sum(quantity) AS num_sold
, sum(quantity*wholesale) AS wholesale_price
, sum(quantity*price) AS retail_price
, sum(quantity*price) - sum(quantity*wholesale) AS profit
FROM (
    SELECT
      tblOrder.*
    , tblItem.description_invoice
    , tblItem.type
    , tblItem.product_number
    , tblItem.quantity
    , tblItem.wholesale
    , tblItem.price
    , tblItem.supplier 
    FROM tblOrder USE KEY (finalized), tblItem
    WHERE
      tblItem.order_id = tblOrder.order_id 
     AND
      finalized=1
     AND
      wholesale <> 0
     AND (order_time >= 1251788400 AND order_time <= 1283669999) 

  UNION 

    SELECT
      tblOrder_archive.*
    , tblItem_archive.description_invoice
    , tblItem_archive.type
    , tblItem_archive.product_number
    , tblItem_archive.quantity
    , tblItem_archive.wholesale
    , tblItem_archive.price
    , tblItem_archive.supplier
    FROM tblOrder_archive USE KEY (finalized), tblItem_archive
    WHERE
      tblItem_archive.order_id=tblOrder_archive.order_id
     AND
      finalized=1
     AND
      wholesale <> 0
     AND (order_time >= 1251788400 AND order_time <= 1283669999)
) AS main_table
GROUP BY
  description_invoice
, supplier,type 
ORDER BY profit DESC;
  • 在WHERE子句中使用的列上创建索引。
  • 删除索引提示: USE KEY (finalized) 如果它做任何事情,可能会使MySQL选择此密钥而不是可能更好的密钥,从而使其速度变慢。
  • 添加一个LIMIT以避免获取太多行。 如果要查看更多行,请使用分页。
  • 使用UNION ALL代替UNION。 这样会更快,因为它不检查重复项,而且您可能也不想删除此处的重复项,因为这会影响总数。

几个月后,订单和项目将移至表的存档版本,以免减慢主表查询的速度。

这可能是一个坏主意。 相反,您应该正确地为数据建立索引,以便在添加更多数据时查询不会显着变慢。 或者,您也可以查看对表进行分区

我将您的查询重新编写为:

   SELECT COALESCE(x.description_invoice, y.description_invoice) AS description_invoice,
          COALESCE(x.supplier, y.supplier) AS supplier,
          COALESCE(x.type, y.type) AS type,
          COALESCE(SUM(x.quantity), 0) + COALESCE(SUM(y.quantity), 0) as num_sold,
          COALESCE(SUM(x.quantity * x.wholesale), 0) + COALESCE(SUM(y.quantity * y.wholesale), 0) AS wholesale_price, 
          COALESCE(SUM(x.quantity * x.price), 0) + COALESCE(SUM(y.quantity * y.price), 0) AS retail_price,
          COALESCE(SUM(x.quantity * x.price), 0) - COALESCE(SUM(x.quantity * x.wholesale), 0) + COALESCE(SUM(y.quantity * y.price), 0) - COALESCE(SUM(y.quantity * y.wholesale), 0) as profit   
     FROM (SELECT o.order_id
             FROM TBLORDER o
            WHERE o.finalized = 1
              AND o.order_time BETWEEN 1251788400 
                                   AND 1283669999
           UNION ALL
           SELECT oa.order_id
            FROM TBLORDER_ARCHIVE oa
           WHERE oa.finalized = 1
             AND oa.order_time BETWEEN 1251788400 
                                   AND 1283669999) a
LEFT JOIN TBLITEM x ON x.order_id = a.order_id
                   AND x.wholesale != 0
LEFT JOIN TBLITEM_ARCHIVE y ON y.order_id = a.order_id
                           AND y.wholesale != 0
 GROUP BY description_invoice, supplier, type 
 ORDER BY profit DESC
  • 您的查询具有UNION ,但我希望不需要从存档表中删除重复项,因此我将其更改为UNION ALL速度更快,因为它不会删除重复项
  • 对于您提供的内容,您拥有SELECT ORDERS.*SELECT ORDER_ARCHIVE.*但从未使用任何列。
  • 聚合函数(SUM)全部位于TBLITEM表上,该表不必要在派生表/内联视图内。
  • 我省略了USE KEY(finalized) ; 您可以根据需要将其重新添加,但是我想与它进行比较-我建议在运行查询之前在两个表上偶尔运行ANALYZE TABLE ,以便优化器具有相对较新的统计信息。
  • 我在finalized列的索引中看不到太多价值,但是我不知道您的数据或使用情况—仅此查询。 但是基于此查询,我将索引:

    1. ORDER_ID
    2. order_time
    3. 敲定

    ...作为覆盖索引-按提供的顺序包含三列的单个索引,因为顺序在覆盖索引中很重要。

我根据您的帮助将其重写如下,并向tblOrder和tblOrder归档文件中添加了推荐的覆盖索引,并且一切似乎都快得多。 但是,我仍然想知道您编写它的方式是否还有其他内容。.但是我还需要使用tblItem_archive和tblOrder_archive一起加入。

SELECT
  description_invoice
, supplier
, type
, sum(quantity) AS num_sold
, sum(quantity*wholesale) AS wholesale_price
, sum(quantity*price) AS retail_price
, sum(quantity*price) - sum(quantity*wholesale) AS profit
FROM (
    SELECT
      tblOrder.order_id
    , tblItem.description_invoice
    , tblItem.type
    , tblItem.product_number
    , tblItem.quantity
    , tblItem.wholesale
    , tblItem.price
    , tblItem.supplier 
    FROM tblOrder, tblItem
    WHERE
      tblItem.order_id = tblOrder.order_id 
     AND
      finalized=1
     AND
      wholesale <> 0
     AND (order_time >= 1251788400 AND order_time <= 1283669999) 

   UNION ALL

    SELECT
      tblOrder_archive.order_id
    , tblItem_archive.description_invoice
    , tblItem_archive.type
    , tblItem_archive.product_number
    , tblItem_archive.quantity
    , tblItem_archive.wholesale
    , tblItem_archive.price
    , tblItem_archive.supplier
    FROM tblOrder_archive, tblItem_archive
    WHERE
      tblItem_archive.order_id=tblOrder_archive.order_id
     AND
      finalized=1
     AND
      wholesale <> 0
     AND (order_time >= 1251788400 AND order_time <= 1283669999)
) AS main_table
GROUP BY
  description_invoice
, supplier,type 
ORDER BY profit DESC;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM