2009-10-13 6 views
2

나는 여러 MySQL 쿼리를 사용하여 사용자 참여/활동을 계산하는 웹 사이트를 운영하고 있습니다.사용자 참여/활동 계산

일반 사용자를 위해 나는 물을 것이다 :

얼마나 많은 업데이트가 만들었다? 사진이 몇 장이나 업로드 되었습니까? 등

관련 테이블, 업데이트, 사진에 대한 기본적인 COUNT 개 검색어입니다. 점수를 얻기 위해 각 점수를 합산합니다. 각 쿼리에는 하나의 JOIN이 필요하며 각 쿼리에는 약 0.0006 초가 소요되며 각 사용자에 대해 총 10 개의 쿼리가 수행되고 0.006 초가 소요됩니다.

한 명의 사용자에게는별로 좋지 않지만 10 분의 이론 처리 시간과 약 1,000,000 개의 DB 쿼리에 대해 100,000 명의 사용자에 대해 계산해야합니다. 내가 잘못된 방식으로 문제에 접근하고있는 것처럼 느껴지고 어떤 아이디어가 있는지 궁금해하고 있었습니까?

사용자 기록에 사용자 점수를 저장하고 특정 작업을 수행 할 때마다 사용자 점수를 늘리는 방법을 생각했지만 유연하지는 않습니다 (다시 돌아가서 특정 날짜에 얼마나 많은 점수가 발생했는지 확인할 수는 없습니다). 예를 들어).

도움을 주시면 큰 도움이됩니다.

+0

서버에 시간이 없습니까? 예를 들어 아침 4시에 서버가 10 분 조금 느린 경우 문제가되지 않습니까? – powtac

+0

그게 내가 계획 한 것이지만 몇 가지 검사를하고 모든 것을 계산하는 데 얼마나 많은 일을 할 것인지 깨달았을 때 내가 어쩌면 잘못된 방식으로 접근하고 있다고 생각하게 만들었습니다 – Jim

답변

2

가 구성되어, 당신은 총 "활동"을 얻기 위해 같은 것을 할 수있는 사용자가 수행 한 :

SELECT users.user_id, 
     (update_counts.update_count + photo_counts.photo_count) AS activity_count 
FROM users 
    INNER JOIN 
     (
     SELECT updates.user_id AS user_id, 
       COUNT(updates.*) AS update_count 
     FROM updates 
     GROUP BY user_id 
     ) AS update_counts ON users.user_id = update_counts.user_id 
    INNER JOIN 
     (
     SELECT photos.user_id AS user_id, 
       COUNT(photos.*) AS photo_count 
     FROM photos 
     GROUP BY user_id 
     ) AS photo_counts ON users.user_id = photo_counts.user_id 
GROUP BY users.user_id 

은 분명히 당신은 테이블을 추가 할 수 있습니다 당신이 필요로하고 당신이 적합하다고 생각하는대로 물건을 비울 수 있습니다. 각 테이블의 user_id 필드에 대한 인덱스가 있으면 테이블이 얼마나 커지는 지에 따라 다르지만 실제로는 잘 수행되어야합니다.

테이블이 커지면 캐시 테이블에서 activity_count를 캐싱해야합니다. 물론 필요한 경우 날짜별로 값을 캐시 할 수 있습니다.

대략적인 추정 만하면되는 경우, 일정한 빈도로 (예 : 매일 밤마다)이 쿼리를 실행하고 결과를 캐시 할 수 있습니다. 캐시 테이블을 업데이트하기 위해 모든 테이블에 트리거를 작성하는 것보다 덜 관입적입니다.

+0

감사합니다. 몇 가지 테스트를하겠습니다 만이 패션에 대한 JOIN은 별도의 쿼리보다 빠릅니까? 나는 전체적인 쿼리의 감소가 도움이되고 있다고 생각한다. – Jim

+0

원래 게시물에서 각 사용자의 점수를 개별적으로 계산하는 것처럼 들린다. 조인을 사용하고 동시에 모든 사람의 결과를 얻는 것은 각 조인 된 테이블의 user_id 인덱스에 대해 하나의 완전한 통과 만 필요하기 때문에 각 사용자의 결과를 한 번에 하나씩 얻는 것보다 빠릅니다 (user_id에 인덱스가 있으면 ' user_id 당 행 수를 얻기 위해 테이블 ​​자체를 건드릴 필요가 없다.) –

+0

도움을 주신 James에게 감사드립니다. 아 아! 이 방법은 활동 여부에 관계없이 각 사용자의 점수를 계산합니까 (활동이없는 사용자는 점수가 0 점이됩니까)? 나는 그것을 테스트 해 왔으며 각 테이블에 활동이있는 사용자 만 반환하는 것으로 보입니다. INNER JOIN을 LEFT JOIN으로 변경하고 NULL activity_count 값을 0으로 변경하는 것이 간단한 문제입니까? – Jim

2

user_activity 링크 테이블이 있어야합니다. action_id, user_idtimestamp이 필요합니다. 예를 들어 사용자가 사진을 업로드하면 activity_id = 2 (activities 테이블에서 참조한 '사진 업로드'의 경우), user_id 및 현재 타임 스탬프로 레코드가 생성됩니다. 이는 쉽게 쿼리 할 수 ​​있으며 많은 사용자가있는 경우 장기 실행 쿼리에 대한 걱정을 없애줍니다.

0

11 웨이 조인을하고 싶지 않으면 각 사용자 업데이트 후에 삽입하는이 목적을 위해 별도의 테이블을 만듭니다.

해당 테이블에는 사용자 이름, 타임 스탬프, 섹션 (테이블의 출처) 및 다른 테이블의 고유 ID가 있어야하므로 삭제에 대한 역 참조를 가질 수 있습니다.

0

정말 필요하기 전에 최적화하려고하는 것처럼 나에게 들립니다. 10 만 명의 사용자가없는 경우 필요 할 때까지 이러한 문제에 대해 걱정할 필요가 없습니다.

최적화가 필요없는 이유가 없다고해서, 아직 해결하지 못한 문제를 너무 과장하려고하지 마십시오.

약간의 불일치가있을 수 있지만 로그인 할 때 (memcached를 사용하여) 각 사용자의 계산 결과를 캐싱하고 카운트 중 하나를 업데이트 할 때 캐시 만 업데이트 할 수 있습니다. 사용자가 매우 활발한 경우 매시간 만 업데이트하는 것이 더 효율적입니다. 각 테이블은 어떤 종류의 user_id 필드가 어디에 테이블을 가정

+0

현재 40,000 명의 사용자가 있으므로, 3 ~ 4 분 정도면 보일 것입니다. 약간 걱정되는 시간의 짧은 공간에서 400,000 개의 쿼리가 있습니다! – Jim

0

이것은 과도한 응용 프로그램 일 수 있지만 항상 OLAP 경로로 이동할 수 있습니다. 이를 통해 사용자 및 시간 범위와 같은 여러 차원에서 사전 집계 된 측정 값을 가질 수 있습니다. 이를 통해 다양한보고 요구에 맞는 유연한 프레임 워크를 얻을 수 있습니다. SQL Server Analysis Services 패키지는 우리 회사에서 잘 작동했습니다.

+0

감사합니다. – Jim