2015-01-30 2 views
0
내가 정렬 결과를 간단 해 보이는 문제를 해결하는 방법을 이해하는 데 문제가

에 의해 순서, 비교 얼마나 많은 다른 사용자와 사용자 등과 같은 과일 등 ID 1, 가장 일치하는 사람을 세어 내림차순으로 결과를 표시합니다.MySQL은 <p></p> 내가 비교하려는 .. 카운트

사용자 :

1 jack 
2 john 
3 jim 

과일 :

id, title 
1 apple 
2 banana 
3 orange 
4 pear 
5 mango 

관계 : 2 개 인덱스 (USER_ID, fruit_id) 및 (fruit_id, USER_ID)

user_id, fruit_id 
1  1 
1  2 
1  5 
2  1 
2  2 
2  4 
3  3 
3  1 

예상 결과 : (과 비교 Jack이 좋아하는 과일 (user_id = 1))

user_id, count 
1   3 
2   2 
3   1 

검색어 :

SELECT user_id, COUNT(*) AS count FROM relations 
WHERE fruit_id IN (SELECT fruit_id FROM relations WHERE user_id=1) 
GROUP BY user_id 
HAVING count>=2 

더 많은 "최적화"쿼리

SELECT user_id, COUNT(*) AS count FROM relations r 
WHERE EXISTS (SELECT 1 FROM relations WHERE user_id=1 and r.fruit_id=fruit_id) 
GROUP BY user_id 
HAVING count>=2 

2 경기의 최소 수있다. (미래에 필요)

설명 :

id select_type   table  type possible_keys key  key_len  ref     rows Extra 
1 PRIMARY    r   index NULL   uid  8   NULL    15  Using where; Using index 
2 DEPENDENT SUBQUERY relations eq_ref xox,uid   xox  8   r.relations,const 1  Using where; Using index 

모든 내가

그럼 내가 볼 카운트 DESC BY ORDER를 사용하려고 할 때까지 잘 작동 : 일시적으로 사용; filesort 사용

임시 테이블이나 파일을 사용하고 싶지 않습니다. 미래에는 데이터베이스가 높은 부하를 받아야하기 때문입니다.

저는 이것이 SQL이 정의되고 작동되는 방식입니다. 그러나 나는 다른 방법으로 그것을하는 방법을 알아낼 수 없다? 임시 테이블 및 파일을 사용하지 않습니다.

가장 많이 일치하는 사용자를 먼저 표시해야합니다.

제발 도와주세요.

UPD : Walker Farrow (파일롯을 사용하는 쿼리)에서 몇 가지 테스트를 수행했습니다.

20,000 rows - avg 0.05 seconds 
120,000    0.20 sec. 
1,100,000   2.9 sec. 

실망스러운 결과. 테이블 구조를 변경하는 것은 가능할 것입니다.하지만 이러한 계산 및 정렬을 통해 - 어떻게해야할지 모르겠습니다.

이 작업을 수행하는 방법에 대한 제안 사항이 있습니까? 아마

+0

글쎄, 문제가되지 않는다면 프로그래밍 언어 부분에서 정렬 메커니즘을 바꿀 수 있습니다. – Prateek

+0

예, 소수의 결과 만 있다면 쉽게 될 것입니다. 문제는 사용자 수 (일치 항목 수)입니다. 여러 페이지에 걸쳐 데이터를 표시하는 중 ... –

+0

글쎄, 아마도이 답변은 [SQL 쿼리 최적화 임시 테이블을 피하기 위해] 도움이 될 수도 있습니다 (http://stackoverflow.com/questions/11896271/sql-query-optimization-to-avoid-temporary). -표). – Prateek

답변

0

,이 같은 하위 쿼리를 생성하고 외부 쿼리에 의해 주문하는 것이 작업을 수행하는 가장 좋은 방법 : 추가해야하는 이유 또한

select * 
from (
    SELECT user_id, COUNT(*) AS count FROM relations r 
    WHERE EXISTS (SELECT 1 FROM relations WHERE user_id=1 and r.fruit_id=fruit_id) 
    GROUP BY user_id 
    HAVING count(*)>=2 
    ) x 
order by count desc 

, 나도 몰라를 exists.다음과 같이 말할 수 있습니까?

select * 
from (
    SELECT user_id, COUNT(*) AS count FROM relations r 
    WHERE user_id=1 
    GROUP BY user_id 
    HAVING count(*)>=2 
    ) x 
order by count desc 

?

잘 모르겠습니다. 아마도 누락되었습니다. 도움이되는 호프!

+0

내가 첫 번째 쿼리에 대한 질문이, 설명 * 관계에 인덱스를 의미 : 'ID \t SELECT_TYPE \t 테이블 \t 유형 \t이 possible_keys \t 키 \t있는 key_len \t 심판 \t 행 \t 추가 PRIMARY \t ALL \t NULL filesort 를 사용 \t \t NULL \t NULL \t NULL 012 DERIVEDr \t 인덱스 \t NULL \t \t uid NULL 여기서 using; 그 결과 (3 행)에 "filesort"를 사용 그래서 index'을 사용하여 인덱스 3 \t D. 부질 \t 관계 eq_ref \t \t \t \t XOX UID XOX 8 \t \t \t 1 r.relations 사용. 이 "filesort 사용"이 미래에 문제가 될 수 있습니까? DB가 커지면 5 천만 행이됩니까? –

+0

두 번째 쿼리 정보. 그것은 잘못된 것입니다. 왜냐하면 그것은 단지 요한의 가장 좋아하는 열매 (ID : 1)를 계산하기 때문입니다. 우리는 다른 사람들과 비교할 필요가 있습니다. 여기서 첫 번째 쿼리를 최적화하는 방법 (IN 연산자 사용) [EXISTS 전략을 사용하여 하위 쿼리 최적화] (http://dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists) .html) –

관련 문제