如何优化此查询?

时间:2011-01-24 20:54:30

标签: mysql optimization subquery join

以下查询获取我需要的信息。但是,我注意到随着表的增长,我的代码越来越慢。我猜它是这个查询。这可以用不同的方式来提高效率吗?我听说过很多关于使用连接而不是子查询的事情,但是,我并没有“得到”如何做到这一点。

  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

3 个答案:

答案 0 :(得分:0)

我会将查询分成更小的块,可能使用存储过程。例如,从事务中获取max ids并将其放入表变量中。然后将其与子事务联系起来。这将使您和编译器更容易计算出正在发生的事情。 也不知道你的桌子上有什么索引,很难提供更多建议

答案 1 :(得分: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没有任何关联。它们具有相同的相关别名,它们指的是同一个表,但它们完全是独立的选择和结果。

因此,您在第一个不相关子查询中所做的是获取positions中所有transactions的最大ID。

然后您将所有transaction.position.max(id)加入result2result2恰好是所有transaction.positionsubtransactions的联接。 (内部order by也是毫无意义和昂贵的,但这不是主要问题。)

您将每个transaction.position.max(id)加入到每个(无论结果2选择)。

点击编辑,回家后:好的,你不是笛卡儿,“MAXid = id”将result1加入result2。但是你仍然在两个查询中汇总transaction的所有行。

所以你得到了一个笛卡尔联接 - 每个result1加入到每个result2,无条件地(没有任何东西告诉数据库,例如,他们应该加入(max) )id或按位置。

因此,如果position.max(id)中有十个唯一的transaction,那么您将获得100行。 1000个独特的位置,一百万行。等

如果你想编写一个像这样的复杂查询,如果你用简单的视图编写它就会容易得多。特别是,您可以自己测试每个视图,以确保获得合理的结果,然后加入视图。

答案 2 :(得分:0)

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