Php 需要帮助优化复杂的MySQL查询吗
我在下面有这个问题。涉及的主要表有4个:tblOrder、tblItems、tblOrder_归档、tblItem_归档。订单和项目在几个月后转移到表的存档版本,以避免减慢主表查询的速度。销量和流量都很高。因此,为了获得销售数据,我从每套存档和非存档表格中选择我需要的。。联合他们。。在工会上组织一个小组。。然后计算一下结果 问题是,对于任何大量的行,订单时间跨度。。查询运行的时间太长,以至于超时。我已经添加了我能想到的所有键,但仍然运行得非常慢 我还可以做更多的事情来加快跑步速度吗?我可以写得不同吗?我可以使用不同的索引吗 或者我应该先编写一个脚本,从每个表集中获取数据,然后在php脚本中进行数学运算以将它们组合起来 谢谢你的帮助Php 需要帮助优化复杂的MySQL查询吗,php,sql,mysql,aggregate-functions,Php,Sql,Mysql,Aggregate Functions,我在下面有这个问题。涉及的主要表有4个:tblOrder、tblItems、tblOrder_归档、tblItem_归档。订单和项目在几个月后转移到表的存档版本,以避免减慢主表查询的速度。销量和流量都很高。因此,为了获得销售数据,我从每套存档和非存档表格中选择我需要的。。联合他们。。在工会上组织一个小组。。然后计算一下结果 问题是,对于任何大量的行,订单时间跨度。。查询运行的时间太长,以至于超时。我已经添加了我能想到的所有键,但仍然运行得非常慢 我还可以做更多的事情来加快跑步速度吗?我可以写得不
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_存档之间必须有连接。。在联接之前,对两个查询使用聚合函数。