Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 需要帮助优化复杂的MySQL查询吗_Php_Sql_Mysql_Aggregate Functions - Fatal编程技术网

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

Php 需要帮助优化复杂的MySQL查询吗,php,sql,mysql,aggregate-functions,Php,Sql,Mysql,Aggregate Functions,我在下面有这个问题。涉及的主要表有4个:tblOrder、tblItems、tblOrder_归档、tblItem_归档。订单和项目在几个月后转移到表的存档版本,以避免减慢主表查询的速度。销量和流量都很高。因此,为了获得销售数据,我从每套存档和非存档表格中选择我需要的。。联合他们。。在工会上组织一个小组。。然后计算一下结果 问题是,对于任何大量的行,订单时间跨度。。查询运行的时间太长,以至于超时。我已经添加了我能想到的所有键,但仍然运行得非常慢 我还可以做更多的事情来加快跑步速度吗?我可以写得不

我在下面有这个问题。涉及的主要表有4个:tblOrder、tblItems、tblOrder_归档、tblItem_归档。订单和项目在几个月后转移到表的存档版本,以避免减慢主表查询的速度。销量和流量都很高。因此,为了获得销售数据,我从每套存档和非存档表格中选择我需要的。。联合他们。。在工会上组织一个小组。。然后计算一下结果

问题是,对于任何大量的行,订单时间跨度。。查询运行的时间太长,以至于超时。我已经添加了我能想到的所有键,但仍然运行得非常慢

我还可以做更多的事情来加快跑步速度吗?我可以写得不同吗?我可以使用不同的索引吗

或者我应该先编写一个脚本,从每个表集中获取数据,然后在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子句中使用的列上创建索引。 删除索引提示:使用密钥。如果它做了任何事情,它可能只是让MySQL选择这个键而不是一个可能更好的键,从而使它变得更慢。 添加限制以避免获取太多行。如果要查看更多行,请使用分页。 使用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表上,这在派生表/内联视图中是不必要的。 我省略了键的用法;如果愿意,您可以重新添加它,但我会比较它和不添加它-我建议在运行查询之前偶尔在两个表上运行,以便优化器具有相对新的统计信息。 我看不到最终确定的列上的索引有多大价值,但我不知道您的数据或用途——只知道这个查询。但基于此查询,我将索引:

订单号 订购时间 定稿 …作为覆盖索引—一个包含三列的索引,按提供的顺序排列,因为顺序在覆盖索引中很重要


基于您的帮助,我将其改写如下,并将推荐的覆盖索引添加到tblOrder和tblOrder归档中,速度似乎要快得多。但我还是想知道,你写这封信的方式是否还有别的地方。。但我也需要使用tblItem_归档和tblOrder_归档

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;

您能告诉我们您创建了哪些索引键吗?并查看EXPLAIN。这是一个很好的方式来了解查询在幕后是如何实际处理的。它还可以给你一个可以改进的想法,这不考虑tblItem_归档表。它和tblOrder_存档之间必须有连接。。在联接之前,对两个查询使用聚合函数。