2013-03-07 3 views
0

웹 사이트의 코스 페이지에 대한 사용자 방문을 추적하고 있습니다. 저는 어떤 코스 (일명 제품)에 대해서도 사용자가 방문한 최상위 코스 페이지 목록을 볼 수 있으며 Amazon의 "이 항목을 본 고객 또한 본 페이지"와 같이 현재 페이지를 방문했습니다. 특색.MySQL - 테이블에서 관련 항목 선택

내가 가지고있는 것은 작동하지만 수집 된 데이터가 계속 증가함에 따라 쿼리 시간이 상당히 느려지고 느려집니다. 이제 약 300,000 개의 레코드가 있고 쿼리는 각각 2 초 이상 걸리고 있습니다. 우리는 약 2M 레코드에 도달 할 때 데이터를 잘라 내기 시작할 것으로 예상하고 있지만 현재 우리가 직면하고있는 성능 문제를 고려할 때 이것이 가능할 것이라고는 생각하지 않습니다. 내가이 일을하는 방법에 대한 더 나은 접근 방법이 있는지 알고 싶습니다.

는 여기에 사용자 ID, 코스 번호와 타임 스탬프를 포함하는 간단한 3 열 InnoDB의 테이블을 가지고

... 피투성이의 세부 사항입니다. 사용자 ID와 코스 번호 필드는 결합되어 있으며 사용자 ID/코스 번호가 결합되어 있습니다. 다음은 테이블 스키마는 다음과 같습니다

테이블에
CREATE TABLE IF NOT EXISTS `coursetracker` (
    `user` varchar(38) NOT NULL COMMENT 'user guid', 
    `course` char(8) NOT NULL COMMENT 'subject code and course number', 
    `visited` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'last visited time', 
    UNIQUE KEY `ndx_user_course` (`user`,`course`), 
    KEY `ndx_user` (`user`), 
    KEY `ndx_course` (`course`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='tracking user visits to courses'; 

데이터는 다음과 같습니다

user         | course | visited 
=======================================|==========|==================== 
{00001A4C-1DE0-C4FB-0770-A758A167B97E} | OFFC2000 | 2013-01-19 23:18:03 
{00001FB0-179E-1E28-F499-65451E5C1465} | FSCT8481 | 2013-01-30 13:12:29 
{0000582C-5959-EF2B-0637-B5326A504F95} | COMP1409 | 2013-01-13 16:09:42 
{0000582C-5959-EF2B-0637-B5326A504F95} | COMP2051 | 2013-01-13 16:20:41 
{0000582C-5959-EF2B-0637-B5326A504F95} | COMP2870 | 2013-01-13 16:25:41 
{0000582C-5959-EF2B-0637-B5326A504F95} | COMP2920 | 2013-01-13 16:24:40 
{00012C64-2CA1-66DD-5DDC-B3714BFC91C3} | COMM0005 | 2013-02-18 21:32:36 
{00012C64-2CA1-66DD-5DDC-B3714BFC91C3} | COMM0029 | 2013-02-18 21:34:04 
{00012C64-2CA1-66DD-5DDC-B3714BFC91C3} | COMM0030 | 2013-02-18 21:34:50 
{00019F46-6664-28DD-BCCD-FA6810B4EBB8} | COMP1409 | 2013-01-16 15:48:49 

내가 어떤 주어진 과정에 관련 과목을 얻기 위해 사용하고 샘플 쿼리 (COMP1409이 예에서) , 다음과 같습니다 :이 쿼리의

SELECT `course`, 
     count(`course`) c 
FROM `coursetracker` 
WHERE `user` IN 
     (SELECT `user` 
     FROM `coursetracker` 
     WHERE `course` = 'COMP1409') 
    AND `course` != 'COMP1409' 
GROUP BY `course` 
ORDER BY c DESC LIMIT 10 

결과는 다음과 같다 :

course | c 
=========|==== 
COMP1451 | 470 
COMP1002 | 367 
COMP2613 | 194 
COMP1850 | 158 
COMP1630 | 156 
COMP2617 | 126 
COMP2831 | 119 
COMP2614 | 95 
COMP1911 | 79 
COMP1288 | 76 

그래서 위의 모든 내용은 성능을 제외한 원하는대로 작동합니다. 테이블은 너무 간단해서 색인을 생성할만한 것이 없습니다. SQL 쿼리는 내가 찾고있는 데이터를 가져옵니다. 이 작업을 더 빠르게 수행하는 방법에 대한 아이디어가 없습니다. 이 접근법에 대한 의견을 보내 주시면 감사하겠습니다.

+1

쿼리의 "설명"을 게시 할 수 있습니까? – m4573r

+0

완전성을 위해 내 [원본 쿼리] (http://oi49.tinypic.com/k9dh7t.jpg) 및 m4573r의 [제안 쿼리] (http://oi46.tinypic.com/ 2m85u9l.jpg). – Brandon

답변

1

당신은 가입 대신에 시도 할 수 있습니다 : 하드

SELECT c1.`course`, 
     count(c1.`course`) as c 
FROM `coursetracker` c1 
INNER JOIN `coursetracker` c2 
ON c1.`user` = c2.`user` 
WHERE c2.`course` = 'COMP1409' 
AND c1.`course` != 'COMP1409' 
GROUP BY c1.`course` 
ORDER BY c DESC LIMIT 10 
+0

빙고! 빨리. 첫 번째 쿼리는 0.0134 초가 걸렸습니다. 1300 개 이상의 코스에서 평균 0.008768124 초/쿼리를 실행합니다. 감사! – Brandon

0

을 더 빠를 것 자체에 테이블에 합류 어쩌면 당신은 EXPLAIN보고 있지만없이 말할?

SELECT `course`, count(`course`) c 
FROM `coursetracker` c 
INNER JOIN `coursetracker` c2 ON c.user = c2.user 
WHERE c2.`course` = 'COMP1409' 
AND c.`course` != 'COMP1409' 
GROUP BY `course` 
ORDER BY c DESC LIMIT 10 
관련 문제