我创建了一个查询,它从两个表中收集数据,对它们进行求和,并显示案例的数量和总和:
SELECT
count(ut.id) AS total
, ( SUM(internal_account) - SUM(( SELECT
SUM( ub.bill_summs )
FROM
u_billing ub
WHERE
ub.bill_types = 'correction'
AND ub.contract_id = ut.contract_id
)) ) AS summ
FROM
u_transactions ut
WHERE
ut.nulled = 0
AND ut.type = 'comission'
AND ut._status = 'not_paid'
AND DATE( ut.add_timestamp ) = DATE( '2012-05-11' );
但它真的很慢。在测试用例中,它给出了这个结果:
+-------+-------+
| total | summ |
+-------+-------+
| 182 | 15105 |
+-------+-------+
1 row in set (4.13 sec)
在182个案例中只有4.13秒而且只有1天,但我的实时服务器有超过600k的案例,所以这将非常慢。
任何想法,我如何重写查询以获得更好的性能?
重新构建查询的解决方案:
DELETE FROM tmpContractSums;
INSERT INTO tmpContractSums
SELECT
ub.contract_id
, SUM( ub.bill_summs ) AS bill_summs
FROM
u_billing ub
WHERE
ub.bill_types = 'correction'
GROUP BY ub.contract_id;
SELECT
count(ut.id) AS total
, ( SUM(internal_account) - SUM(bill_summs) )
FROM
u_transactions ut
LEFT JOIN tmpContractSums t ON ut.contract_id = t.contract_id
WHERE
ut.nulled = 0
AND ut.type = 'comission'
AND ut._status = 'not_paid'
AND ut.add_timestamp BETWEEN '2012-05-11 00:00:00' AND '2012-05-11 23:59:59';
执行时间: 500ms
PS:因为我不能用webuser删除表,所以我刚刚创建了表:
CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0;
我正在删除记录。没有下降那么快,但仍然比原来快。
答案 0 :(得分:1)
如何简单地使用“临时”表?
DROP TABLE IF EXISTS tmpContractSums;
CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0;
INSERT INTO tmpContractSums
SELECT
ub.contract_id
SUM( ub.bill_summs ) AS bill_summs
FROM
u_billing ub
WHERE
ub.bill_types = 'correction'
GROUP BY ub.contract_id;
SELECT
count(ut.id) AS total
, ( SUM(internal_account) - COALESCE(bill_summs, 0) )
FROM
u_transactions ut
LEFT JOIN tmpContractSums t ON ut.contract_id = t.contract_id
WHERE
ut.nulled = 0
AND ut.type = 'comission'
AND ut._status = 'not_paid'
AND ut.add_timestamp BETWEEN '2012-05-11' AND '2012-05-11 23:59:59';
这应该更快,如果你想要,你可以添加索引到“临时表”,或者如果你有足够的空间,可以使它成为一个带有engine = memory的表。
或者:
DROP TABLE IF EXISTS tmpContractSums;
CREATE TABLE tmpContractSums AS SELECT contract_id, bill_summs FROM u_billing WHERE 1 = 0;
INSERT INTO tmpContractSums
SELECT
ub.contract_id
SUM( ub.bill_summs ) AS bill_summs
FROM
u_billing ub
WHERE
ub.bill_types = 'correction'
GROUP BY ub.contract_id;
SELECT
count(ut.id) AS total
, ( SUM(internal_account) - (SELECT bill_summs FROM tmpContractSums t WHERE ut.contract_id = t.contract_id ) )
FROM
u_transactions ut
WHERE
ut.nulled = 0
AND ut.type = 'comission'
AND ut._status = 'not_paid'
AND ut.add_timestamp BETWEEN '2012-05-11' AND '2012-05-11 23:59:59';
答案 1 :(得分:0)
希望这有帮助
SELECT
COUNT(A.id) AS total,
(SUM(A.internal_account) - SUM(COALESCE(B.bill_sums, 0)) AS 'Sum'
FROM
u_transactions A
LEFT JOIN u_billing B on A.contract_id = B.contract_id
WHERE
A.nulled = 0 AND
A.type = 'comission' AND
A._status = 'not_paid' AND
DATE(A.add_timestamp) = DATE('2012-05-11')
AND B.bill_types = 'correction';
编辑:
我没有注意到你对子查询的结果求和。:
SELECT
count(ut.id) AS total
, ( SUM(internal_account) - **SUM**(( SELECT
**SUM**( ub.bill_summs )
FROM
u_billing ub
WHERE
ub.bill_types = 'correction'
AND ub.contract_id = ut.contract_id
)) ) AS summ
FROM
u_transactions ut
也许你可以用合并来代替总和:
-COALESCE(( SELECT
**SUM**( ub.bill_summs )
FROM
u_billing ub
WHERE
ub.bill_types = 'correction'
AND ub.contract_id = ut.contract_id
),0)
答案 2 :(得分:0)
不是吗?我的意思是它必须更好地工作。
SELECT
count(ut.id) AS total
, SUM(internal_account - COALESCE(ub.b_summs, 0)) summ
FROM u_transactions ut
LEFT JOIN
(
SELECT
contract_id,
SUM(bill_summs) b_summs
FROM u_billing
WHERE bill_types = 'correction'
GROUP BY contract_id
) AS ub
ON ub.contract_id = ut.contract_id
WHERE
ut.nulled = 0
AND ut.type = 'comission'
AND ut._status = 'not_paid'
AND DATE( ut.add_timestamp ) = DATE( '2012-05-11' );
此外,您必须避免在应用于表列的WHERE子句上使用函数。如果你有索引,使用函数不允许索引使用。请改用:
AND ut.add_timestamp >= DATE( '2012-05-11' ) AND ut.add_timestamp < DATE( '2012-05-12' );
答案 3 :(得分:0)
这应该可以加快速度:
SELECT
COUNT(ua.id) as total,
SUM(ua.internal_account - ua.corrections) as 'sum'
FROM (
SELECT
ut.id,
ut.internal_account,
SUM(COALESCE(ub.bill_sums, 0)) AS corrections
FROM
u_transactions ut
LEFT JOIN u_billing ub on ut.contract_id = ub.contract_id
WHERE
ut.nulled = 0 AND
ut.type = 'comission' AND
ut._status = 'not_paid' AND
DATE(ub.add_timestamp) = DATE('2012-05-11') AND
ut.bill_types = 'correction'
GROUP BY
ut.id
) as ua
修改:更正add_timestamp
表格前缀并插入缺失的GROUP BY