2011-05-20 96 views
0

我正在做一个项目,我正在跟踪网站上的用户,我在网站上记录他们的每一个命中。每当他们点击一个URL时,我都会在数据库中创建它,并使用一些标签对其进行标记。按加入查询中的日期进行排序和计算

每个网址在我的数据库中都被命名为“资源”,并且资源可以使用多个标记进行标记。访问者在访问URL时连接到资源,当用户访问资源时,我也将日期连接到它。

我想要做的事情是找到具有正确标签的资源,这些资源在本月或今天已被观看。

我目前正在建设的查询是在这里:

SELECT r.resource_id, r.resource_url 
FROM resource r 
JOIN visitor_resource vt ON vt.resource_id = r.resource_id 
JOIN resource_tags rt ON rt.resource_id = vt.resource_id 
JOIN tags t ON t.tag_id = rt.tag_id AND t.tag_name = '42' 
GROUP BY r.resource_id 

为了给你一个想法的结构,你可以在这里看到: tracking database structure http://kaspergrubbe.dk/db-overview.png

所以基本上我会到那里算多少visitor_resources通过查看上个月的visitor_resources.last_visited并在5个访问量最高的资源中查找。

如何解决这个问题?

上面的查询似乎也很慢没有查询缓存,我怀疑这是因为t.tag_name不是一个索引,这是一个varchar,但有无论如何加快进程,而不是添加此索引?

谢谢。

+0

如果你只存储last_visited日期,这实际上并不会告诉你的资源了多少次访问。在我猜测的同一个月中,访问者可能会不止一次地访问资源。也许没关系,你只关心独特的访​​问者,但我想我应该指出。 – 2011-05-20 15:04:32

+0

感谢您指出,但这是设计:) – 2011-05-20 15:20:51

回答

1

您已经忽略了基于日期的任何条件,所以您应该添加该条款并查看性能如何变化。另外,如果你正在寻找一个计数,那么你也应该添加。我认为mySQL支持LIMIT子句(而不是TOP),因此添加它以将其限制为5个访问量最大的资源。随着一切融合在一起恐怕也会是这个样子:

SELECT 
    r.resource_id, 
    r.resource_url, 
    COUNT(*) 
FROM 
    Visitor_Resources VR 
INNER JOIN Resources R ON R.resource_id = VR.resource_id 
INNER JOIN Resource_Tags RT ON RT.resource_id = R.resource_id 
INNER JOIN Tags T ON 
    T.tag_id = RT.tag_id AND 
    T.tag_name = '42' 
WHERE 
    VR.last_visited BETWEEN <start of month> AND <end of month> 
GROUP BY 
    r.resource_id, 
    r.resource_url 
ORDER BY 
    COUNT(*) DESC 
LIMIT 5 

对不起,我没有做很多的MySQL的这些天,所以我不知道开始和结束日期参数是什么样子的最后一行。

除非您的标签表格非常大,否则索引可能无关紧要。 Visitor_Resources.last_visited上的索引虽然可能是个好主意。

此外,我在查询中更改了您的表名,使其更加一致。我个人喜欢复数名字,但单数也可以。不管你选择哪一个,选择一个并坚持下去。

+0

添加一个索引visitor_resource.last_visited花了半小时,但查询运行在5秒,而最初的50秒。谢谢! – 2011-05-20 16:55:46

+0

..和5秒就足够了,因为缓存:-) – 2011-05-20 17:00:05

-1

Kasper,

首先您需要调整您的JOIN。没有必要说在每条线上加入:

ie. 
     LEFT JOIN(
     groups, sign 
     )ON(
     user.user_id = groups.userID AND 
     groups.group_id = sign.groupID 

尝试类似的连接。

然后在该子句中添加一个ORDER BY。

ORDER BY last_visited DESC LIMIT 5; 

这将整理您的日期表,并采取从以往列指定最近的5个条目。

希望这会有所帮助。