优化Mysql查询

时间:2014-11-24 01:17:16

标签: mysql

这是我希望优化的查询:

SELECT Id, Title, Text,
(SELECT count(*) from ReaderFeedback as b
where b.EmailAddress=ReaderFeedback.EmailAddress) AS totalPosts
FROM ReaderFeedback FORCE INDEX (ParentFeedbackId)
WHERE ParentFeedbackId = 123 AND Approved=1 ORDER BY Date ASC

下面是Mysql解释查询结果:

    id: 1
    select_type: PRIMARY
    table: ReaderFeedback
    Type: ref
    possible_keys :ParentFeedbackId
    Key: ParentFeedbackId
    key_len: 7
    ref: const,const
    rows: 2
    Extra: Using where; Using filesort

    id: 2
    DEPENDENT SUBQUERY
    b
    ALL
    NULL
    NULL
    NULL
    NULL
    101369
    Using where

如果出现以下情况,请显示create table freader feedback:

CREATE TABLE `ReaderFeedback` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ParentFeedbackId` int(11) DEFAULT NULL,
`Text` text NOT NULL,
`Title` varchar(75) NOT NULL DEFAULT '',
`EmailAddress` varchar(75) NOT NULL DEFAULT '',
`Date` date NOT NULL DEFAULT '0000-00-00',
`Approved` tinyint(4) DEFAULT '1',
PRIMARY KEY (`Id`),
KEY `ParentFeedbackId` (`ParentFeedbackId`,`Approved`),
KEY `Title` (`Title`),
KEY `Id` (`Id`),
KEY `Approved` (`Approved`),
) ENGINE=MyISAM AUTO_INCREMENT=142781 DEFAULT CHARSET=utf8

请帮助开发人员。

谢谢!

2 个答案:

答案 0 :(得分:2)

好的,让我们打破这个。

首先,您使用相关子查询来获取帖子计数。让我们把它变成一个连接的聚合子查询。这可以获得每个不同电子邮件地址的行数。

      SELECT COUNT(*) AS Count,
             EmailAddress
        FROM ReaderFeedback
       GROUP BY EmailAddress

然后,让我们将其加入到您的其他查询中,就像这样。

SELECT a.Id, a.Title, a.Text
       b.Count
  FROM ReaderFeedback AS as
  JOIN (
          SELECT COUNT(*) AS Count,
                 EmailAddress
            FROM ReaderFeedback
           GROUP BY EmailAddress
       ) AS b ON a.EmailAddress = b.EmailAddress
 WHERE a.ParentFeedbackID = 123
   AND a.Approved = 1
 ORDER BY a.Date ASC

这应该比你已经做的好一点。

比这更进一步涉及试验索引。以下是一些可以尝试的事情。

  1. (ParentFeedbackID, Approved, EmailAddress, Date)上创建复合索引。这可能(或可能不)有助于满足外部查询。
  2. (EmailAddress)上创建索引。这很可能有助于满足内部GROUP BY查询。

答案 1 :(得分:1)

如果没有看到您的表格结构和查询的解释计划,很难提供太多帮助

但是,请尝试此查询,因为它可以为您提供更好的结果。

SELECT R.Id, R.Title, R.Text, b.totalPosts
FROM ReaderFeedback R
INNER JOIN (
    SELECT EmailAddress, count(*) AS totalPosts
    FROM ReaderFeedback
    WHERE ParentFeedbackId = 123 AND Approved=1
    GROUP BYEmailAddress
) AS b ON b.EmailAddress = R.EmailAddress
WHERE R.ParentFeedbackId = 123 AND R.Approved=1 
ORDER BY R.Date

此外,您应该在ReaderFeedback表上添加索引(如果它尚不存在),如此

ALTER TABLE ReaderFeedback  ADD INDEX (EmailAddress, ParentFeedbackId , Approved, Date);

另外,请考虑将Table引擎从MyISAM更改为INNODB。

ALTER TABLE ReaderFeedback ENGINE=INNODB;

您还可以将EmailAddress列更改为CHARACTER SET latin1 COLLATE latin1_general_ci,因为这会使查找部分更快。

ALTER TABLE ReaderFeedback CHANGE `EmailAddress` EmailAddress VARCHAR(75) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,

祝你好运!