2014-11-24 185 views
0

这就是我正在寻找优化查询:优化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 

显示创建表freader反馈若跌破:

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 

请帮助一位开发人员。

谢谢!

+0

您能向我们介绍解释计划吗? (即'EXPLAIN EXTENDED SELECT ..'。)同时向我们展示您的'show create table ReaderFeedback' – Jaylen 2014-11-24 01:22:00

+0

以上更新!谢谢。 – Tom 2014-11-24 01:49:03

+0

是的,你应该考虑下面的答案。添加我提到的索引,并将您的查询更改为联接会更好地执行。另外,考虑将您的引擎更改为innodb而不是MyISAM – Jaylen 2014-11-24 01:56:21

回答

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

没有看到你的表结构和解释计划的查询,很难帮上什么忙

但是,尝试此查询,因为它应该给你更好的结果。

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); 

此外,考虑的MyISAM改变你的表引擎InnoDB的。

ALTER TABLE ReaderFeedback ENGINE=INNODB; 

你也可以改变你的EmailAddressCHARACTER SET latin1 COLLATE latin1_general_ci,因为这将使得查找更快的一部分。

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

祝你好运!