2017-11-14 1 views
1

두 개의 테이블 이벤트와 user_device가 있습니다. eventsuser_device에는 공통 필드 device_id이 있습니다.조인 된 테이블로 마지막 5 개의 행을 가져와야하는 쿼리를 최적화하는 방법

user_device 테이블의 필드는 user_iddevice_id입니다. 기본적으로 모든 장치를 보유하는 user_device 테이블은 사용자에게 속합니다.

events 모든 이벤트를 보유하는 테이블은 장치에 속합니다.

이제 특정 사용자에 대해 마지막 5 개의 알림을 받고 싶습니다.

그래서 아래 두 테이블을 결합하여 쿼리를 만들었습니다.

SELECT * 
FROM events 
LEFT JOIN user_device ON user_device.deviceid=events.deviceid 
WHERE user_device.userid=101 
ORDER BY events.id DESC 
LIMIT 5 

이벤트 테이블에는 4 백만 개가 넘는 레코드가 있습니다. 이 쿼리는 결과를 반환하는 데 30 초가 걸립니다.

ORDER BY을 제거하면 쿼리에 2 초 밖에 걸리지 않습니다.

어떻게 최적화 할 수 있습니까?

+0

특정 레코드를 얻었 으면 수동으로 작성하고 쿼리에서'* '를 제거하십시오. – Bhargav

+1

쿼리 성능에 관한 섹션을 자세히 읽으십시오. http://meta.stackoverflow.com/a/271056/ 질문을 작성하여 세부 정보를 제공해주십시오. –

답변

0

테이블에 인덱스가 없기 때문에 평소보다 오래 걸리는 경우가 많습니다. deviceId에 대한 색인을 추가하면 userId가 쿼리 속도에 많은 도움이됩니다.

SELECT * 
FROM events 
LEFT JOIN user_device ON user_device.**deviceid**=events.**deviceid** 
WHERE user_device.**userid**=101 
ORDER BY events.id DESC 
LIMIT 5 

굵은 글씨에는 빠른 '후크'를위한 색인이 필요합니다. by by는 색인을 요구하지 않습니다.

+0

감사합니다. @ naveed-ramzan – LahiruTM

1

처음 : 사용하지 마십시오 SELECT *. 대신 원하는 열의 이름을 지정하십시오.

두 번째 : user_device.userid에서 일치하는 항목을 찾고 있습니다. 따라서 user_deviceuserid 열로 시작하는 색인이 필요합니다. 같은 테이블에 deviceid 값을 사용합니다. 따라서이 색인을 만드십시오. covering index이라고합니다.

ALTER TABLE user_device ADD INDEX x_user_device (userid, deviceid); 

셋째 : 그런 다음 id에 의해 주문, deviceid에 의해 events의 행을 찾고 있습니다. 따라서이 두 열에 다른 covering index이 필요합니다.

ALTER TABLE events ADD INDEX x_device_id (deviceid, id); 

넷째 : 당신은 WHERE 절에 LEFT 조인 된 테이블에서 열을 언급. 이것은 LEFT JOIN을 일반적인 내부 JOIN으로 변환합니다. 그래서 JOIN을 사용하십시오.

제 5 : SELECT * ... ORDER BY ... LIMIT은 악명 높은 성능의 반 패턴입니다. 왜? 기록을 완전히 엉망으로 만들어 버리고 몇 가지를 제외한 모든 것을 버리십시오. 대신이 방법을 사용해보십시오. 먼저 서브 쿼리를 사용하여 관련 events.id 값을 가져옵니다.

  SELECT events.id 
      FROM events 
      JOIN user_device ON user_device.deviceid=events.deviceid 
      WHERE user_device.userid=101 
      ORDER BY events.id DESC 
      LIMIT 5 

하위 쿼리를 테스트하십시오. 5 개의 관련 이벤트 ID 값을 제공해야하며 실제로이를 매우 빠르게 수행해야합니다.이 하위 쿼리를 사용하여 두 테이블에서 필요한 세부 정보를 찾으십시오.

SELECT events.*, user_device.*  /* not optimal. list only the columns you need */ 
    FROM (
      SELECT events.id 
      FROM events 
      JOIN user_device ON user_device.deviceid=events.deviceid 
      WHERE user_device.userid=101 
      ORDER BY events.id DESC 
      LIMIT 5 
     ) sel 
    JOIN events ON sel.id = events.id 
    JOIN user_device ON events.deviceid = user_device.deviceid 

이것을 지연 조인 쿼리 패턴이라고합니다. id 값의 모든 더미에서 모든 순서를 수행 한 다음 몇 개의 레코드 만 추출합니다.

이렇게하면 데이터베이스가 커짐에 따라 성능을 계속 확인할 수 있습니다.

+0

감사합니다. @ O.Jones. 이 설명은 많은 도움이되었습니다. – LahiruTM

관련 문제