2016-08-31 24 views
1

私はチャットメッセージのテーブルが4m以上の行に成長しています。大規模なテーブルで日付範囲を最適化する

特定の期間内にユーザーとの間でメッセージを送受信する必要があります。

最初はこのクエリは大丈夫でしたが、テーブルの現在のサイズでは長すぎます(> 10秒)。

私は多くのインデックスの組み合わせを作成しようとしました。 MySQLはmessageType + sentDateに複合インデックスを使用しています

SELECT `ofMessageArchive`.* 
FROM `ofMessageArchive` 
WHERE `ofMessageArchive`.`messageType` IN ('Message') 
AND (ofMessageArchive.fromJID = '[email protected]' OR ofMessageArchive.toJID = '[email protected]') 
AND (ofMessageArchive.sentDate > '1462235333109') 
ORDER BY ofMessageArchive.sentDate ASC LIMIT 50 

どのように私はこのクエリを最適化できますか?

[EDIT] EXPLAIN結果:

+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+ 
| id | select_type | table   | type | possible_keys                                              | key     | key_len | ref | rows | Extra  | 
+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+ 
| 1 | SIMPLE  | ofMessageArchive | ref | index_ofMessageArchive_on_fromJID_and_toJID,index_ofMessageArchive_on_sentDate,index_ofMessageArchive_on_messageType,idxMessageTypeSentDate,ofMessageArchive_fromjid_idx,ofMessageArchive_tojid_idx | idxMessageTypeSentDate | 767  | const | 731570 | Using where | 
+----+-------------+------------------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------+---------+-------+--------+-------------+ 
+1

結果を説明し、このクエリ –

+0

追加の 'EXPLAIN'結果を入力してください – Paludis

答えて

0

あなたは直接ユーザー名、上のインデックスを使用することはできませんので、あなたは、受信メッセージに異なった送信メッセージを処理する問題(基本的に正規化の問題)に走りましたおそらく最も重要な価値です。あなたがそれらをまだ持っていない場合

、インデックスを作成ofMessageArchive(fromJID, messageType, sentDate)ofMessageArchive(toJID, messageType, sentDate)(多分異なるために、あなたはこれらの列のそれぞれ、あなたが使用しているもの、他のquerysを持っている、しかしで始まるどのように多くの異なる値に応じて、この注文)。

unionを使用し、これらのインデックスを使用するには:

select * from  
((SELECT `ofMessageArchive`.* 
    FROM `ofMessageArchive` 
    WHERE (ofMessageArchive.fromJID = '[email protected]') 
    AND `ofMessageArchive`.`messageType` IN ('Message') 
    AND (ofMessageArchive.sentDate > '1462235333109') 
    ORDER BY ofMessageArchive.sentDate ASC LIMIT 50 
) union 
    (SELECT `ofMessageArchive`.* 
    FROM `ofMessageArchive` 
    WHERE (ofMessageArchive.toJID = '[email protected]') 
    AND `ofMessageArchive`.`messageType` IN ('Message') 
    AND (ofMessageArchive.sentDate > '1462235333109') 
    ORDER BY ofMessageArchive.sentDate ASC LIMIT 50 
) 
) s 
order by s.sentDate ASC LIMIT 50 
関連する問題