2

メンバーが受け取ったメッセージの一覧が表示されるページを構築しようとしています。この mySQL クエリを思いつきましたが、実行速度が非常に遅いです。実行には少なくとも 10 秒かかります。

SELECT senderid,
       receiverid
FROM   messages
WHERE  ( receiverid, sentdate ) IN (SELECT receiverid,
                                           Max(sentdate)
                                    FROM   messages
                                    WHERE  receiverid = '1'
                                    GROUP  BY senderid)
ORDER  BY sentdate DESC 

これは私が使用しているデータベースです:

`autoID` mediumint(11) unsigned NOT NULL AUTO_INCREMENT
`senderID` mediumint(11) unsigned DEFAULT '0'
`receiverID` mediumint(11) unsigned DEFAULT '0'
`sentDate` datetime DEFAULT '0000-00-00 00:00:00'
「メッセージ」ロングテキスト
主キー (`autoID`)
KEY `receiverID` (`receiverID`)
KEY `senderID` (`senderID`)

データベースには 150,000 エントリしかありません。そのmySQLデータベースのみを搭載した専用サーバーを実行しています。

どんな助けでも大歓迎です。

G-Nugget、sentDate にインデックスを追加しましたが、速度は向上しません。これがEXPLAINです(申し訳ありませんが、方法が示されています。他にどのようにできるかわかりません):

id:1
select_type:PRIMARY
table:messages
type:ALL
possible_keys:null
keys:null
key_len:null
ref:null
rows:149433
Extra:Using where; ファイルソートの使用

id:2
select_type:DEPENDENT SUBQUERY
table:messages
type:ref
possible_keys:receiverID
key:receiverID
key_len:4
ref:const
rows:20
Extra:Using where; 一時的な使用; ファイルソートの使用

4

2 に答える 2

1

あなたが言及した結果セットを生成するためにこのクエリはどうですか?

SELECT m.senderid,
       m.receiverid
  FROM messages m
  JOIN (
            SELECT  max(autoID) autoID, 
                    receiverID, SenderID
              FROM  messages
          GROUP BY  receiverId, SenderID
       ) X on m.autoID = x.AutoId
  WHERE m.receiverId = '1'
  ORDER BY m.autoID desc

これは、autoIDとsentdateの両方が時間の経過とともに単調に増加する可能性が高いという仮定を利用しています。送信者/受信者の個別のペアごとに最新のメッセージのIDを取得し、それらのIDを使用して、表示するメッセージテーブルのサブセットを選択します。

于 2012-11-27T02:14:14.937 に答える
0

MySQL では、サブクエリがin正しく最適化されません。クエリは少し複雑です。クエリを書く効率的な方法だと思います:

SELECT senderid,
       receiverid
FROM   messages m
WHERE  m.receiverid = '1' and
       exists (SELECT 1
               FROM   messages m1
               WHERE  m1.receiverid = '1'
               GROUP  BY m1.senderid
               having max(sentdate) =  m.sentdate)
ORDER  BY sentdate DESC 

あなたのクエリは、各送信から「1」への最新のメッセージを取得しようとしているようです。より単純なバージョンは次のようになります。

select senderid, receiverid
from messages m
where m.receiverid = '1'

つまり、最新の送信日がin条件に一致するため、各送信者 ID が元のクエリに含まれます。まったく同じ日時の 2 人の送信者を持つことができます。そのような重複を表示する必要はありますか?

于 2012-11-27T02:43:56.070 に答える