我有一个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行。这是什么? –