带有从属子查询的MySQL查询 - 如何加快速度?

时间:2013-09-20 10:21:16

标签: mysql

我有一个问题,我正在努力加快速度。我确信有一种方法可以提高效率,但我缺乏知识。

订单 - 这显示每个订单收到一行(目前为800,000行)

orders_financials - 显示与订单相关的每笔金融交易一行(目前为2,000,000行)

orders_financials表每个订单包含多行,交易类别显示在financialType

因此,例如,对于一个订单,orders_financials中可能有5行

financialType = 14: value = 10.00
financialType = 12: value = 7.00
financialType = 18: value = 2.50
financialType = 15: value = 0.30
financialType = 17: value = 7.50

对于每个订单,将有不同数量的数据。随着时间的推移,会向系统添加更多数据,并将新行添加到orders_financials。

我要做的是运行一个查询,允许我为每个订单获取一行,并为此行计算几类金融交易的总计。

下面的查询应该给我所有由customerID 279发出的订单:

select 
orders.orderID, 
customers.username, 
(select group_concat(financialRef) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (17) ) ref,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (17) ) costs_cost,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (12,13) ) costs_exp,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (14) ) costs_sell,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (15) ) costs_sell_out,                                       
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (1,2,3,9,11) ) extras_in,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (4,5) ) extras_out,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (20) ) extras_back,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (18) ) insurance_in,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (10,6) ) insurance_out,
(select sum(amount) from orders_financials where orders_financials.orderID=orders.orderID and financialType IN (19) ) insurance_back                                            
from orders 
left join customers on orders.customerID=customers.customerID 
where customers.customerID='279'
order by orderID

(仅供参考,订单表中有18,263条记录,其中customerID = 279)

您会看到财务类型的12或13可以合计以得出costs_exp。同样1,2 3,9,11都是extras_in。

最终结果是包含大量数据的精彩查询,但它提供了每个订单的详细概述。在where子句中,我可以按客户,服务,日期范围等进行搜索

我的问题是此查询需要年龄才能运行。我必须以非常低效的方式进行,因为查询的每个元素都是快速的。

从慢速日志中我可以看到它正在迭代422,000,000行

Query_time: 528.107584  Lock_time: 0.000652 Rows_sent: 1388  Rows_examined: 422442417

必须有一种更有效的方式,但我很难看到。

编辑 - 以下是上述查询的解释:

+----+--------------------+-------------------+-------+-----------------------+---------------+---------+---------------------------+--------+--------------------------+
| id | select_type        | table             | type  | possible_keys         | key           | key_len | ref                       | rows   | Extra                    |
+----+--------------------+-------------------+-------+-----------------------+---------------+---------+---------------------------+--------+--------------------------+
|  1 | PRIMARY            | customers         | const | PRIMARY               | PRIMARY       | 4       | const                     |      1 |                          |
|  1 | PRIMARY            | orders            | ref   | customerID            | customerID    | 5       | const                     |  24802 | Using where; Using index |
| 12 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | financialType | 4       | const                     |      1 | Using where              |
| 11 | DEPENDENT SUBQUERY | orders_financials | range | orderID,financialType | financialType | 4       | NULL                      |      2 | Using where              |
| 10 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | financialType | 4       | const                     |  49717 | Using where              |
|  9 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | financialType | 4       | const                     |      1 | Using where              |
|  8 | DEPENDENT SUBQUERY | orders_financials | range | orderID,financialType | financialType | 4       | NULL                      |      2 | Using where              |
|  7 | DEPENDENT SUBQUERY | orders_financials | range | orderID,financialType | financialType | 4       | NULL                      |      5 | Using where              |
|  6 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | financialType | 4       | const                     |    139 | Using where              |
|  5 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | orderID       | 4       | p4db_admin.orders.orderID | 236338 | Using where              |
|  4 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | orderID       | 4       | p4db_admin.orders.orderID | 236338 | Using where              |
|  3 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | financialType | 4       | const                     |  99966 | Using where              |
|  2 | DEPENDENT SUBQUERY | orders_financials | ref   | orderID,financialType | financialType | 4       | const                     |  99966 | Using where              |
+----+--------------------+-------------------+-------+-----------------------+---------------+---------+---------------------------+--------+--------------------------+
13 rows in set (0.00 sec)

1 个答案:

答案 0 :(得分:4)

SELECT  a.orderID, 
        b.username,
        GROUP_CONCAT(CASE WHEN c.financialType = 17 THEN c.financialRef END) ref,
        SUM(CASE WHEN c.financialType IN (12,13) THEN c.amount END) costs_cost,
        SUM(CASE WHEN c.financialType = 14 THEN c.amount END) costs_exp,
        SUM(CASE WHEN c.financialType = 15 THEN c.amount END) costs_sell,
        SUM(CASE WHEN c.financialType IN (1,2,3,9,11) THEN c.amount END) extras_in,
        SUM(CASE WHEN c.financialType IN (4,5) THEN c.amount END) extras_out,
        SUM(CASE WHEN c.financialType = 20 THEN c.amount END) extras_back,
        SUM(CASE WHEN c.financialType = 18 THEN c.amount END) insurance_in,
        SUM(CASE WHEN c.financialType IN (10,6) THEN c.amount END) insurance_out,
        SUM(CASE WHEN c.financialType = 19 THEN c.amount END) insurance_back
FROM    orders a
        LEFT JOIN customers b
            ON a.customerID = b.customerID 
        LEFT JOIN orders_financials c
            ON a.orderID = c.orderID
GROUP   BY a.orderID, b.username

orders_financials.financialType

上添加索引
ALTER TABLE orders_financials ADD INDEX (financialType)