簡體   English   中英

使用GROUP BY優化查詢以刪除“使用臨時”; 使用文件排序

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM