我在下面有这个查询。涉及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;
答案 0 :(得分:2)
USE KEY (finalized)
。如果它做任何事情,它可能会让MySQL选择这个密钥而不是一个可能更好的密钥,从而使速度变慢。订单和商品会在几个月后转移到表格的存档版本,以免减慢主表格查询的速度。
这可能是一个坏主意。相反,您应该正确地索引数据,以便在添加更多数据时查询不会变得非常慢。或者您可以查看partitioning the table。
答案 1 :(得分:1)
我将您的查询重写为:
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
- 这更快,因为它不会删除重复项1} LI>
SELECT ORDERS.*
和SELECT ORDER_ARCHIVE.*
但从未使用任何列。TBLITEM
表中,这在派生表/内联视图中是不必要的。USE KEY(finalized)
;如果您愿意,可以重新添加它,但我会与之进行比较 - 我建议在运行查询之前在两个表上偶尔运行ANALYZE TABLE,以便优化程序具有相对较新的统计信息。我在finalized
列的索引中看不到多少值,但我不知道您的数据或使用 - 只是这个查询。但基于此查询,我将索引:
...作为覆盖索引 - 按提供的顺序排列有三列的单个索引,因为顺序在覆盖索引中很重要。
答案 2 :(得分:0)
我根据你的帮助将其重写如下,并为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;