2013-03-07 92 views
0

我正在跟踪用户访问我们网站上的课程页面。我这样做是为了对任何给定的课程(又名产品),我可以列出用户访问过的顶级其他课程页面,他们也访问了当前页面 - 就像亚马逊的“浏览此项目的客户也浏览了”特征。MySQL - 选择表中的相关项目

我的工作是,但随着收集的数据不断增加,查询时间变得越来越慢。我现在已经获得了大约30万条记录,并且每个查询都需要2秒钟。我们希望在达到约2百万条记录时开始修剪数据,但考虑到我们目前面临的性能问题,我认为这是不可能的。我想知道是否有更好的方法来解决我如何做到这一点。

这里是血淋淋的细节...

我有一个包含用户ID,课程号和时间戳一个简单的三列InnoDB表。用户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 2013-03-07 21:55:50

+0

为了完整起见,以下是我的[原始查询](http://oi49.tinypic.com/k9dh7t.jpg)和m4573r的[建议查询](http://oi46.tinypic.com/)的解释结果。 2m85u9l.jpg)。 – Brandon 2013-03-07 22:38:23

回答

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 2013-03-07 22:14:41

0

很难说没有看到你的解释,但也许加盟表本身会更快?

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 
相关问题