2009-07-23 5 views
1

내 사이트의 친구 모듈로 사용자가 서로 친구를 사귈 수 있습니다. 이가 "친구"에 저장되어있는 friendship_inviter과 사물의 거부/승인 끝에있는 사람이되는 우정을 시작한 사람, 테이블 friendhsip_accepter더 빠르게 실행되도록이 쿼리를 어떻게 최적화 할 수 있습니까?

SELECT user_id, user_name, user_gender 
FROM friends 
LEFT JOIN users 
    ON ( users.user_id = friends.friendship_inviter 
     OR users.user_id = friends.friendship_accepter) 
WHERE (friendship_inviter = '125' OR friendship_accepter = '125') 
AND user_id !='125' 
AND friendship_level = 1; 

이 풀 테이블 스캔이에게이며, 테이블이 크지 않더라도 (15,000 명의 사용자, 3000 명의 우정) 평균 1 ~ 1.5 초가 소요됩니다.

서버에 부담을주지 않는 방법으로 현재 친구 목록을 출력하려면 어떻게해야합니까?

+0

user_id는 문자열이 아닙니까? 그렇다면 엄청난 imporvement를위한 int로 만듭니다. – flukus

답변

4
SELECT user_id, user_name, user_gender 
FROM friends 
LEFT JOIN users 
    ON users.user_id = friends.friendship_accepter 
WHERE friendship_accepter = '125' 
AND user_id !='125' 
AND friendship_level = 1 
UNION 
SELECT user_id, user_name, user_gender 
FROM friends 
LEFT JOIN users 
    ON users.user_id = friends.friendship_inviter 
WHERE friendship_inviter = '125' 
AND user_id !='125' 
AND friendship_level = 1; 

, 그것을보고, 당신은 당신의 WHERE 절에 여분의 열을, 그래서 실제로에 해당되는, INNER 대신 조인 작성합니다 왼쪽의 경우 게시 :

SELECT user_id, user_name, user_gender 
FROM friends 
INNER JOIN users 
    ON users.user_id = friends.friendship_accepter 
WHERE friendship_accepter = '125' 
AND user_id !='125' 
AND friendship_level = 1 
UNION 
SELECT user_id, user_name, user_gender 
FROM friends 
INNER JOIN users 
    ON users.user_id = friends.friendship_inviter 
WHERE friendship_inviter = '125' 
AND user_id !='125' 
AND friendship_level = 1; 
+0

예제에서는 레코드가 반환되지 않습니다. –

+0

알았어요. 쿼리의 두 부분 사이에서 accepter/inviter를 전환해야했습니다. –

+0

더 빨라 졌습니까? –

1

WHERE 절과 JOIN에 사용 된 열/조합에 색인을 추가하십시오.

+0

inviter/accepter 행에 UNIQUE 인덱스가 있으므로 서로간에 한 번 친구가 될 수 있고 WHERE 절에 나타나는 각 열의 개별 인덱스가 될 수 있습니다. –

0

user_id, friendship_accepter, friendship_inviter and friendship_level의 색인이 생성되었는지 확인하십시오.

또한 원시 쿼리 시간 만 게시하거나 결과를 출력 할 시간이 포함되어 있습니까? 또한 출력을 포함하는 경우에는 느리지 만 출력은 아닐 수도 있습니다.

결과가 느려질 수있는 또 다른 사항은 인터넷이 느린 네트워크 (예 : 인터넷)에있는 경우입니다. 느린 시간은 질의로 인한 것이 아니기 때문일 수 있습니다. 당신이 "친구"테이블에서 아무 것도 선택하지 않는 것처럼 물론

+0

시간은 명령 행에서 직선입니다. 또한 느린 쿼리 로그에 해당 코드가있는 페이지가 실행될 때마다 나타납니다. –

+0

오른쪽, 테이블 스캔 네트워크 문제가 아닙니다. – duffymo

1

friendhip_level의 카디널리티가 낮을 수 있습니다. 경우에 따라 로우 카디널리티 컬럼에서, 쿼리 옵티마이 저는 어쨌든 테이블 스캔을 결정합니다.

EXPLAIN을 수행하고 friendship_level 조건을 쿼리에서 고려하기 전에 다른 조건이 먼저 실행되는지 확인하십시오. 처음 두 조건이 충족 된 후에 남아있는 레코드를 검사하는 데 시간이 훨씬 더 걸립니다.

+0

+1에 대한 '설명' – MitMaro

0

내 소셜 네트워크 사이트에서 비슷한 점이 있지만 내 방식이 약간 다르다. 각 우정에 대해 2 개의 레코드를 삽입하면 사용자를 표시 할 수 있습니다.

친구 요청 보낸 친구 요청 보류하고 확인 된 친구

I't는 UNION의 사용을 제거, 뭔가 생각합니다. 현재 약 50,000 명의 사용자가 있고 친구 테이블에 1 백만 개가 넘는 행이 있습니다.이 문자는 나에게 매우 유용합니다.

관련 문제