sql查询需要花费大量时间来执行mysql

时间:2014-01-26 18:23:37

标签: mysql sql performance

我有以下查询

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_ledgerr_trans_idtrans_dateledger_codeledger_ref_codecompany_codetrans_typetrans_type_name

ledger_master(ledger_code, company_code)

EXPLAIN

1 SIMPLE a ALL 92553使用where;使用临时;使用filesort 1 SIMPLE b ALL PRIMARY,ledger_code 2338

3 个答案:

答案 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()中的一个,但改进很少。