简体   繁体   English

查询花费太多时间

[英]Query is taking too much time

I want to take your ideas regarding the below query: 我想就以下查询提出您的想法:

select a.expense_code, a.expense_date, a.expense_supplier_code, b.supplier_name, a.expense_discount, a.expense_payment_method, a.expense_payment_transfer_to, a.expense_advance, a.expense_status,
                            sum(c.expense_item_buy_price * c.expense_item_quantity) , d.account_name, a.expense_counter, a.expense_type, a.expense_saving_type, a.expense_payment_transfer_from
                            from expense_data a, supplier_data b, expense_item c, tree_data d
                            where a.expense_supplier_code = b.supplier_code and a.expense_payment_transfer_to= d.account_code
                            and a.expense_counter = c.expense_counter
                            and a.expense_date between '2013-01-01' and '2014-01-01' and a.expense_status = 0 or a.expense_status = 2 group by (a.expense_counter);

This query is taking so much time even though in the expense_data table, there are four indices: 即使在expense_data表中有四个索引,此查询也会花费大量时间:

1- Expense_code. 
2- expense_user_id
3- expense_supplier_code
4- expense_payment_transfer_from

I do not know why it takes so much time is it because of two much join or is it because too much indeces. 我不知道为什么要花这么多时间是因为两次连接,还是因为过多的索引。 Can you please suggest? 你能建议吗?

Could be that your where clause contains a logical error. 可能是您的where子句包含逻辑错误。 Look at the last line (last OR condition): 查看最后一行(last OR条件):

where 
  ....
  and a.expense_counter = c.expense_counter 
  and a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
  and a.expense_status = 0 
  or a.expense_status = 2 

That means "take records between dates etc. AND with status 0, OR take all records with status 2 " 这意味着“获取日期之间的记录,等等,并且状态为0,或者获取状态为2的所有记录

To speed things up, you might want to try to make a combined index on a combination of the columns you join on. 为了加快处理速度,您可能希望尝试对加入的列的组合进行合并索引。 That index might be more useful than the four separate indexes you have now, although you can still keep those. 该索引可能比您现在拥有的四个单独索引更有用,尽管您仍然可以保留它们。 Apart from those four fields, you may even want to experiment by adding status and/or expense_data to the index. 除了这四个字段之外,您甚至还可以尝试通过将status和/或expense_data添加到索引来进行试验。

Recoding it to make the joins clearer (and removing that massive join where if expense status was all tables were joined) gives:- 重新编码以使连接更清晰(并删除大规模连接,如果费用状态是所有表都被连接的话):

SELECT a.expense_code, 
    a.expense_date, 
    a.expense_supplier_code, 
    b.supplier_name, 
    a.expense_discount, 
    a.expense_payment_method, 
    a.expense_payment_transfer_to, 
    a.expense_advance, 
    a.expense_status,
    SUM(c.expense_item_buy_price * c.expense_item_quantity) , 
    d.account_name, 
    a.expense_counter, 
    a.expense_type, 
    a.expense_saving_type, 
    a.expense_payment_transfer_from
FROM expense_data a, 
INNER JOIN supplier_data b ON a.expense_supplier_code = b.supplier_code
INNER JOIN expense_item c ON a.expense_counter = c.expense_counter
INNER JOIN tree_data d ON a.expense_payment_transfer_to= d.account_code
WHERE a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
AND a.expense_status = 0 OR a.expense_status = 2 
GROUP BY (a.expense_counter);

Looking at that it is important that you have an index on supplier_code on the supplier_data table, an index on expense_counter on the expense_item table and an index on account_code on the tree_data table. 看到这一点很重要,您必须在Supplier_data表上的Supplier_code上有一个索引,在Expense_item表上的expense_counter上有一个索引,在tree_data表上的account_code上有一个索引。

I suspect you don't really want to return items with an expense status of 0 and an expense date in that range, with any record of expense status 2 irrespective of date so the following might be what you want:- 我怀疑您真的不希望退回费用状态为0且费用日期在该范围内的项目,而无论费用日期如何,费用状态为2的任何记录,因此以下内容可能是您想要的:

SELECT a.expense_code, 
    a.expense_date, 
    a.expense_supplier_code, 
    b.supplier_name, 
    a.expense_discount, 
    a.expense_payment_method, 
    a.expense_payment_transfer_to, 
    a.expense_advance, 
    a.expense_status,
    SUM(c.expense_item_buy_price * c.expense_item_quantity) , 
    d.account_name, 
    a.expense_counter, 
    a.expense_type, 
    a.expense_saving_type, 
    a.expense_payment_transfer_from
FROM expense_data a, 
INNER JOIN supplier_data b ON a.expense_supplier_code = b.supplier_code
INNER JOIN expense_item c ON a.expense_counter = c.expense_counter
INNER JOIN tree_data d ON a.expense_payment_transfer_to= d.account_code
WHERE a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
AND a.expense_status IN (0, 2)
GROUP BY (a.expense_counter);

You have to put OR condition in brackets: 您必须将OR条件放在方括号中:

SELECT a.expense_code, 
   a.expense_date, 
   a.expense_supplier_code, 
   b.supplier_name, 
   a.expense_discount, 
   a.expense_payment_method, 
   a.expense_payment_transfer_to, 
   a.expense_advance, 
   a.expense_status, 
   SUM(c.expense_item_buy_price * c.expense_item_quantity), 
   d.account_name, 
   a.expense_counter, 
   a.expense_type, 
   a.expense_saving_type, 
   a.expense_payment_transfer_from 
FROM expense_data a, 
   supplier_data b, 
   expense_item c, 
   tree_data d 
WHERE a.expense_supplier_code = b.supplier_code 
   AND a.expense_payment_transfer_to = d.account_code 
   AND a.expense_counter = c.expense_counter 
   AND a.expense_date BETWEEN '2013-01-01' AND '2014-01-01' 
   AND (a.expense_status = 0 OR a.expense_status = 2)
GROUP BY a.expense_counter; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM