2011-10-29 12 views
1

私は1つの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(ID)と共演、しかし、クエリがあまりにも遅かったので、私はこのクエリを思い付いた:

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秒以内に正しいデータを取得できない場合は、可能な限り最速のクエリを使用してデータを取得する必要があります。

したがって、上記のクエリを最適化してより高速に実行するにはどうすればよいですか?このクエリが遅くなることが理由

+0

max(id)でグループ化することについてのあなたのコメントは遅すぎますが、IDの上限100で注文しています...これは、常に同じ100の最初のレコードを返します(ほとんどの場合、欠落した送信者/受信者の組み合わせがセット...あなたは、常に最新のインスタンス、または最新の(最高100)インスタンスの欠落している送信者/受信者ペアを必要としますか? – DRapp

+0

一方で、各送信者/受信者グループごとに100の最も高いID番号が必要だとします。一方、あなたが思いついたクエリが適切なデータを返してくれるとします。しかし、100行しか返しません。どちらですか? –

答えて