我有以下查询
SELECT
b.ledger_name,
a.trans_id,
a.voucher_id,
a.r_trans_id,
a.voucher_number,
date_format(a.trans_date,'%d-%m-%Y') as trans_date,
a.trans_type as voucher_type,
a.trans_type_name,
case when Sum(a.trans_amount) > 0 then round(abs(Sum(a.trans_amount)),2) else 0 end as amount_cr,
case when Sum(a.trans_amount) < 0 then round(abs(Sum(a.trans_amount)),2) else 0 end as amount_dr
FROM transaction_ledger AS a
LEFT JOIN ledger_master AS b
ON b.company_code = a.company_code
AND b.ledger_code = a.ledger_ref_code
WHERE a.ledger_code = '31'
AND a.company_code = '65370928-9ee1-40f6-ac38-e7a381908fd9'
AND a.trans_date BETWEEN '2010-04-01' AND '2014-01-31'
AND a.trans_type_name in('Sales', 'Purchase', 'Receipt', 'Payment', 'Journal' ,'Credit Note', 'Debit Note', 'Contra')
GROUP BY b.ledger_name,
a.trans_id,
a.voucher_id,
a.r_trans_id,
a.voucher_number,
a.trans_date,
a.company_code,
a.narration,
a.trans_type,
a.trans_type_name
ORDER BY date_format(a.trans_date,'%Y-%m-%d'), a.voucher_number;
表transaction_ledger有大约200,000条记录。上面的查询需要太多时间来执行。我还在需要的地方创建了索引。什么可能导致延迟?
以下是一些细节:
索引
transaction_ledger
(r_trans_id
,trans_date
,ledger_code
,ledger_ref_code
,company_code
,trans_type
,trans_type_name
)
ledger_master(ledger_code, company_code)
EXPLAIN
1 SIMPLE a ALL 92553使用where;使用临时;使用filesort 1 SIMPLE b ALL PRIMARY,ledger_code 2338
答案 0 :(得分:0)
我的ledger_master表上有一个索引ON(ledger_code)
在您的transaction_ledger表上,您需要最符合查询需求的列。在这种情况下
(company_code,ledger,trans_date,trans_type_name)
另外,左连接的“ON”条件在那里有公司代码和where子句,你应该只在WHERE子句中需要它
SELECT
b.ledger_name,
a.trans_id,
a.voucher_id,
a.r_trans_id,
a.voucher_number,
date_format(a.trans_date,'%d-%m-%Y') as trans_date,
a.trans_type as voucher_type,
a.trans_type_name,
case when Sum(a.trans_amount) > 0 then round(abs(Sum(a.trans_amount)),2) else 0 end as amount_cr,
case when Sum(a.trans_amount) < 0 then round(abs(Sum(a.trans_amount)),2) else 0 end as amount_dr
FROM
transaction_ledger AS a
LEFT JOIN ledger_master AS b
a.ledger_ref_code = b.ledger_code
WHERE
a.company_code = '65370928-9ee1-40f6-ac38-e7a381908fd9'
AND a.ledger_code = '31'
AND a.trans_date BETWEEN '2010-04-01' AND '2014-01-31'
AND a.trans_type_name in ('Sales', 'Purchase', 'Receipt', 'Payment', 'Journal' ,'Credit Note', 'Debit Note', 'Contra')
GROUP BY
b.ledger_name,
a.trans_id,
a.voucher_id,
a.r_trans_id,
a.voucher_number,
a.trans_date,
a.company_code,
a.narration,
a.trans_type,
a.trans_type_name
ORDER BY
date_format(a.trans_date,'%Y-%m-%d'), a.voucher_number;
答案 1 :(得分:0)
您可以使用transaction_ledger
上的附加索引加快速度:
transaction_ledger(ledger_code, company_code, trans_type_name, trans_date)
请注意,这是一个包含四列的索引,而不是四列包含一个索引。
此外,您不需要在左外连接-- you have it in the
中进行公司比较,其中clause (this doesn't affect performance but it cleans up the query). So change the
来自`子句:
FROM transaction_ledger a left outer join
ledger_master b
ON b.ledger_code = a.ledger_ref_code
至于解释可能导致延迟的原因,您需要对查询执行explain
并在问题中显示结果。
答案 2 :(得分:0)
也许您可以避免使用LEFT JOIN
,因为可以删除一个条件而另一个条件可以在WHERE
子句上进行测试:
SELECT
b.ledger_name,
a.trans_id,
a.voucher_id,
a.r_trans_id,
a.voucher_number,
date_format(a.trans_date,'%d-%m-%Y') as trans_date,
a.trans_type as voucher_type,
a.trans_type_name,
case when Sum(a.trans_amount) > 0 then round(Sum(a.trans_amount),2) else 0 end as amount_cr,
case when Sum(a.trans_amount) < 0 then round(abs(Sum(a.trans_amount)),2) else 0 end as amount_dr
FROM transaction_ledger AS a, ledger_master AS b
WHERE a.ledger_code = '31'
AND a.company_code = '65370928-9ee1-40f6-ac38-e7a381908fd9'
AND a.trans_type_name in('Sales', 'Purchase', 'Receipt', 'Payment', 'Journal' ,'Credit Note', 'Debit Note', 'Contra')
AND b.ledger_code = a.ledger_ref_code --this was in the join
AND a.trans_date > '2010-04-01'
AND a.trans_date <'2014-01-31'
GROUP BY b.ledger_name,
a.trans_id,
a.voucher_id,
a.r_trans_id,
a.voucher_number,
a.trans_date,
a.company_code,
a.narration,
a.trans_type,
a.trans_type_name
ORDER BY date_format(a.trans_date,'%Y-%m-%d'), a.voucher_number) as x
此外,你可以用2个条件替换BETWEEN,并设置限制性排序的条件(第一个更具限制性),因为你只有AND条件,如果第一个不满足则没有必要继续测试其他人。
修改强>
你也可以避免abs()
中的一个,但改进很少。