2011-01-24 137 views
0

以下查询获取我需要的信息。但是,我注意到,随着表的增长,我的代码变得越来越慢。我猜这是这个查询。这可以写一个不同的方式,使其更有效率?我听说很多关于使用连接而不是子查询,但是,我不“得到”如何去做。如何优化此查询?

SELECT * FROM 

    (SELECT MAX(T.id) AS MAXid 
    FROM transactions AS T 
    GROUP BY T.position 
    ORDER BY T.position) AS result1, 

    (SELECT T.id AS id, T.symbol, T.t_type, T.degree, T.position, T.shares, T.price, T.completed, T.t_date, 
    DATEDIFF(CURRENT_DATE, T.t_date) AS days_past, 
    IFNULL(SUM(S.shares), 0) AS subtrans_shares, 
    T.shares - IFNULL(SUM(S.shares),0) AS due_shares, 

    (SELECT IFNULL(SUM(IF(SO.t_type = 'sell', -SO.shares, SO.shares)), 0) 
    FROM subtransactions AS SO WHERE SO.symbol = T.symbol) AS owned_shares 

    FROM transactions AS T 
    LEFT OUTER JOIN subtransactions AS S 
    ON T.id = S.transid  
    GROUP BY T.id 
    ORDER BY T.position) AS result2 

    WHERE MAXid = id 
+1

你可以发布你的表的CREATE语句与索引? – 2011-01-24 20:57:43

回答

0

您的代码:

(SELECT MAX(T.id) AS MAXid 
    FROM transactions AS T  [<--- here ] 
    GROUP BY T.position 
    ORDER BY T.position) AS result1, 

    (SELECT T.id AS id, T.symbol, T.t_type, T.degree, T.position, T.shares, T.price, T.completed, T.t_date, 
    DATEDIFF(CURRENT_DATE, T.t_date) AS days_past, 
    IFNULL(SUM(S.shares), 0) AS subtrans_shares, 
    T.shares - IFNULL(SUM(S.shares),0) AS due_shares, 

    (SELECT IFNULL(SUM(IF(SO.t_type = 'sell', -SO.shares, SO.shares)), 0) 
    FROM subtransactions AS SO WHERE SO.symbol = T.symbol) AS owned_shares 

    FROM transactions AS T  [<--- here ] 

通知的[<---- here ]马克我添加到您的代码。

第一个T与第二个T没有任何关系。它们具有相同的相关别名,它们引用同一个表,但它们完全是独立的选择和结果。

所以你在第一个做什么,不相关的,子查询获得transactions所有positions的最大ID。

然后你要加入所有transaction.position.max(id) s到result2(这result2恰好是所有transaction.position S的subtransactions联接)。 (和内部order by是没有意义的,成本高了,但是这不是主要的问题。)

你即将加入每transaction.position.max(id)每一个(无论结果2种选择)。

上编辑,回家后:好吧,你不Cartesianing, “在哪里MAXid = ID” 不加入result1result2。但是,您仍然在两个查询中汇总了所有行transaction

所以你得到一个笛卡儿连接 - 每个result1加入到每一个result2,无条件地(没有告诉数据库,例如,他们应该由(最大值)的ID或位置加入)。

因此,如果您在transaction中有十个唯一的position.max(id) s,您会得到100行。 1000个独特的职位,一百万行。等

当你想写这样一个复杂的查询,如果你从更简单的视图组成它更容易。尤其是,您可以自行测试每个视图,以确保您获得合理的结果,然后加入视图。

+0

由于使用了一个聚合函数(`SUM()`),所以你会看到糟糕的表现。 – 2011-01-24 21:13:13

0

我会将查询拆分成更小的块,可能使用存储过程。例如,从事务中获取最大ID并将其放入表变量中。然后加入子事务。这将使您和编译器更容易了解正在发生的事情。 同样不知道索引你的桌子上有什么就很难提供更多的建议

0

在代码中添加一个基准函数。然后计算代码的每个部分以确定发生减速的位置。通常情况下,减速会发生在与您第一次猜测不同的查询中。在发布到计算器之前,确定需要优化的正确查询。