2014-11-24 293 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, 

祝你好運!