2016-08-31 2 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 

이 쿼리를 어떻게 최적화 할 수 있습니까?

[편집] 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' 결과를 제공하십시오 :

이 인덱스를 사용하려면 union 사용 – Paludis

답변

0

당신이 직접 이름에 인덱스를 사용할 수 있도록, 수신 메시지 다르게 보내는 메시지를 처리하는 문제 (기본적으로 정규화 문제)에 달렸다 아마도 가장 중요한 가치 일 것입니다. 당신이 아직없는 경우

, 인덱스를 생성 ofMessageArchive(fromJID, messageType, sentDate)ofMessageArchive(toJID, messageType, sentDate) (아마도 다른 순서로, 당신은이 컬럼의 각각의 사용 어떤 다른 querys에 대한,하지만 시작 얼마나 많은 다른 값에 따라 이 순서).

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 
관련 문제