MYSQL将行转换为列性能问题

时间:2010-04-16 12:41:09

标签: sql mysql performance

我正在执行一个查询,将行转换为类似于this post的列,但遇到了性能问题。这是查询: -

SELECT
    Info.Customer,
    Answers.Answer,
    Answers.AnswerDescription,
    Details.Code1,
    Details.Code2,
    Details.Code3
FROM
    Info
    LEFT OUTER JOIN Answers
    ON Info.AnswerID = Answers.AnswerID
    LEFT OUTER JOIN
    (SELECT
      ReferenceNo,
      MAX(CASE DetailsIndicator WHEN 'cde1' THEN DetailsCode ELSE NULL END ) Code1,
      MAX(CASE DetailsIndicator WHEN 'cde2' THEN DetailsCode ELSE NULL END ) Code2,
      MAX(CASE DetailsIndicator WHEN 'cde3' THEN DetailsCode ELSE NULL END ) Code3
    FROM DetailsData
    GROUP BY ReferenceNo) Details
    ON Info.ReferenceNo = Details.ReferenceNo
    WHERE Info.Date BETWEEN x AND y

返回的行数少于300行,但“详细信息”表约为18万行。 查询需要45秒才能在一半的时间内运行。 请注意,内部查询需要7秒才能运行。

当我在MYSQL中输入show processlist;时,它挂在“发送数据”上。

有关性能问题可能是什么的任何想法?

3 个答案:

答案 0 :(得分:2)

首先,查询“详细信息”结果的内部子选择是查询所有条目...这是你想要的吗?我不这么认为。您似乎只希望根据符合外部日期检查的参考编号获得结果。

所以,我会改变你的内部选择以包括......

FROM DetailsData 
where DetailsData.ReferenceNo IN 
    ( select distinct Info2.ReferenceNo
        from Info Info2 where Info2.Date between x and y )
GROUP BY ReferenceNo) Details 

这样,您只能获得与相关日期范围内的参考号相关的详细信息。

答案 1 :(得分:1)

首先,我将在子查询中移动where.dd和Details和Info的连接。

此外,Details.ReferenceNo和Info.Date是否已编入索引?

编辑: 好吧,这是我想到的版本

SELECT
    Details.Customer,
    Answers.Answer,
    Answers.AnswerDescription,
    Details.Code1,
    Details.Code2,
    Details.Code3
FROM
    (SELECT
      Info.Customer,
      Info.AnswerID,
      Info.ReferenceNo,
      MAX(CASE DetailsIndicator WHEN 'cde1' THEN DetailsCode ELSE NULL END ) Code1,
      MAX(CASE DetailsIndicator WHEN 'cde2' THEN DetailsCode ELSE NULL END ) Code2,
      MAX(CASE DetailsIndicator WHEN 'cde3' THEN DetailsCode ELSE NULL END ) Code3
    FROM Info LEFT JOIN DetailsData ON Info.ReferenceNo = Details.ReferenceNo
    WHERE Info.Date BETWEEN x AND y
    GROUP BY ReferenceNo) Details
    LEFT OUTER JOIN Answers ON Details.AnswerID = Answers.AnswerID

所以第一次迭代是减少子查询中生成的记录数(原因:它的源有几百条记录,并且有聚合,所以mysql必须构建一个结果集以便进一步加入) - 在感觉DRapp的解决方案与此类似。

但问题是,是否真的有必要提供子查询?看看下面将如何执行

将是有意义的
SELECT
    Info.Customer,
    Answers.Answer,
    Answers.AnswerDescription,
    MAX(CASE DetailsIndicator WHEN 'cde1' THEN DetailsCode ELSE NULL END ) Code1,
    MAX(CASE DetailsIndicator WHEN 'cde2' THEN DetailsCode ELSE NULL END ) Code2,
    MAX(CASE DetailsIndicator WHEN 'cde3' THEN DetailsCode ELSE NULL END ) Code3
FROM
    FROM Info 
    LEFT JOIN DetailsData ON Info.ReferenceNo = DetailsData.ReferenceNo
    LEFT OUTER JOIN Answers ON Details.AnswerID = Answers.AnswerID
WHERE Info.Date BETWEEN x AND y
GROUP BY ReferenceNo

鉴于结果中只有数百条记录,并且如果有索引覆盖连接和选择条件,我希望上面的内容在适度的硬件上以不到一秒的速度返回结果。

(查询未经测试)

答案 2 :(得分:0)

尝试使用“EXPLAIN”来定义哪个查询很慢