[英]Optimizing query with GROUP BY to remove Using Temporary; Using Filesort
我正在使用mySQL 5.6.13.2,並有一個查詢,該查詢涉及父表中的150,000行和子表中的1M以上的行。 如果我刪除GROUP BY(僅作為測試),查詢將花費2秒,如果我擁有GROUP BY,則查詢將花費6秒以上。
我讀過其他有關如何使用臨時刪除的文章。 使用文件排序,但是這些不能解決問題。 我希望在這里能得到一些幫助。
可以在此處找到展示所有這些的SQL提琴: http : //sqlfiddle.com/#!9/edeb6/1
CREATE TABLE `summary` (
`RunID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`LastUpdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`FileName` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`XCount` int(11) DEFAULT NULL,
`YCount` int(11) DEFAULT NULL,
`AccountID` varchar(25) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`RunID`),
KEY `acct-lastupdate` (`AccountID`,`LastUpdate`),
KEY `acct-lastupdate-counts` (`AccountID`,`LastUpdate`,`XCount`,`YCount`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `detail` (
`DetailID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`LastUpdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`RunID` int(10) unsigned DEFAULT NULL,
`TestID` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
`ResultCode` int(11) DEFAULT NULL,
PRIMARY KEY (`DetailID`),
KEY `detail_runid` (`RunID`),
KEY `detail_testid` (`TestID`),
KEY `detail_runid_testid_result` (`RunID`,`TestID`,`ResultCode`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
這是我的查詢的EXPLAIN輸出:
EXPLAIN select
testid as 'TestID',
sum(case when resultcode = 1 then 1 else 0 end) as Category1,
sum(case when resultcode = 2 then 1 else 0 end) as Category2,
sum(case when resultcode = 0 then 1 else 0 end) as Category3
from detail d, summary s
where s.accountid = 'xyz'
and s.lastupdate >= '2014-05-26 00:00:00'
and s.lastupdate < '2014-07-27 00:00:00'
and s.runid = d.runid
and s.runid <= 9999999999
GROUP BY testid;
1 SIMPLE s ref PRIMARY,acct-lastupdate,acct-lastupdate-counts acct-lastupdate 78 const 2 Using where; Using index; Using temporary; Using filesort
1 SIMPLE d ref detail_runid,detail_runid_testid_result detail_runid 5 db_9_edeb6.s.RunID 1 (null)
如果我刪除GROUP BY,則說明說“在哪里使用”; 使用沒有臨時或文件排序的索引,查詢將在2秒而不是6秒內運行。
必須將這些結果按測試ID分組。 而且,測試ID值是任意的,並且事先未知,因此將無法用帶有針對硬編碼的已知測試ID的子查詢來編寫查詢。
是否可以定義其他索引來停止臨時和文件排序? 如果不是,是否有更富創造性的方式來重寫此查詢,從而提高效率並可能解決該問題?
請注意,在我的查詢的GROUP BY確實具有一些HAVING和ORDER BY條件之后(具體來說,它會... GROUP BY testid具有Category1 OR Category2 OR Category3按Category1 desc,Category 2 desc的順序;“-但是,我在示例中省略了它在這里,因為無論使用或不使用擴展子句,我都能獲得相同的性能和EXPLAIN輸出,並且我想使示例盡可能簡單。我在這里提到它是因為如果您有一種創造性的方式來重寫查詢(如果可以的話),請這將是很好的。
如前所述,這里有一個SQL提琴http://sqlfiddle.com/#!9/edeb6/1演示了此問題(因此您可以看到EXPLAIN輸出和實驗)。
謝謝!
如果可以選擇,請嘗試將“ accountid”字段添加到“ detail”表中。 然后,您無需加入此查詢的摘要表。 從查詢中刪除“摘要”表,並將“ s”別名指向“ d”。 然后EXPLAIN僅使用where顯示。 但我不知道它是否比您的速度快得多。
語句“ sum(case,結果代碼= 1,然后1,否則0,結束)”可以這樣寫:“ sum(resultcode = 1)作為Category1,sum(reusltcode = 2)作為Category2 ...”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.