我有一個MySQL表:MySQL:如何優化這個簡單的GROUP BY + ORDER BY查詢?
CREATE TABLE IF NOT EXISTS `test` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`SenderId` int(10) unsigned NOT NULL,
`ReceiverId` int(10) unsigned NOT NULL,
`DateSent` datetime NOT NULL,
`Notified` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`Id`),
KEY `ReceiverId_SenderId` (`ReceiverId`,`SenderId`),
KEY `SenderId` (`SenderId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
該表通過以下步驟填充了10.000隨機行來進行測試:
DELIMITER //
CREATE DEFINER=`root`@`localhost` PROCEDURE `FillTest`(IN `cnt` INT)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE intSenderId INT;
DECLARE intReceiverId INT;
DECLARE dtDateSent DATE;
DECLARE blnNotified INT;
WHILE (i<=cnt) DO
SET intSenderId = FLOOR(1 + (RAND() * 50));
SET intReceiverId = FLOOR(51 + (RAND() * 50));
SET dtDateSent = str_to_date(concat(floor(1 + rand() * (12-1)),'-',floor(1 + rand() * (28 -1)),'-','2008'),'%m-%d-%Y');
SET blnNotified = FLOOR(1 + (RAND() * 2))-1;
INSERT INTO test (SenderId, ReceiverId, DateSent, Notified)
VALUES(intSenderId,intReceiverId,dtDateSent, blnNotified);
SET i=i+1;
END WHILE;
END//
DELIMITER ;
CALL `FillTest`(10000);
問題:
我需要編寫一個查詢,這將組由「SenderId,ReceiverId」並返回第100最高的I DS每個組,被Id以升序下令。
我打了GROUP BY,ORDER BY和MAX(同上),但查詢速度太慢了,所以我想出了這個查詢:
SELECT SQL_NO_CACHE t1.*
FROM test t1
LEFT JOIN test t2 ON (t1.ReceiverId = t2.ReceiverId AND t1.SenderId = t2.SenderId AND t1.Id < t2.Id)
WHERE t2.Id IS NULL
ORDER BY t1.Id ASC
LIMIT 100;
上述查詢返回正確的數據,但它當test
表的行數超過150.000時,它變得太慢。在150.000行上述查詢需要7秒鐘才能完成。我希望test
表中有500.000之間 - 1M行,查詢需要在不到3秒返回正確的數據。如果無法在3秒內獲取正確的數據,則需要使用盡可能快的查詢來獲取數據。
那麼,怎樣才能在上面的查詢進行優化,使其運行速度更快?
您有關MAX(ID)太慢了分組,但現在由ID限100訂貨評論...總是返回相同的100條第一記錄(主要是......直到失蹤發送器/接收器組合添加到組...您是否總是希望預先發送實例,或最近(最高100個)缺少發送者/接收者對的實例。 – DRapp
一方面,你說你想爲每個發件人/收件人組設置100個最高的ID號碼。另一方面,你說你提出的查詢返回正確的數據。但它只返回100行。這是什麼? –