2012-01-20 107 views
5

我需要跟踪在我网站上在线的用户,这样我才能在在线用户的头像旁边显示“在线”图标。为什么我这样做时我的MySQL查询速度很快,而当我这样做时速度很慢?

的检测,第一步是跟踪当用户最后一次露面的,所以我每次用户请求页面的时间做一个UPDATE查询:

UPDATE `users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

现在,经过这一权利,我执行另一个查询,这一次得到我的网站的所有用户的某些准则下,所以我可以在主页上显示出来:

SELECT *, 
(ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) AS SearchRadius 
FROM `users` 
INNER JOIN `profiles` ON (
    users.user_id = profiles.user_id 
) 
WHERE (users.latitude > 38.904216788163 AND users.latitude < 42.501503211837) 
AND (users.longitude > -76.252301637251 AND users.longitude < -71.507178362749) 
AND (ACOS(SIN(0.7103989219783) * SIN(RADIANS(users.latitude)) + COS(0.7103989219783) * COS(RADIANS(users.latitude)) * COS(RADIANS(users.longitude) - -1.2894447135174)) * 6371) < 200 AND users.sex = '1' AND users.seeking = '2' AND users.user_id != '1' AND users.account_status = '1' LIMIT 0, 10 

没关系此查询的疯狂,基本的一点是,我来自同一个users选择表,我以前更新ING。

当我陆续执行这些2个查询一个这些是我得到的时间:

1st query: 0.0392 seconds 
2nd query: 1.5396 seconds 

这会导致页面加载时间明显的延迟。

现在,当我创建了一个单独的表在线用户和第一查询改成这样:更快

1st query: 0.0411 seconds 
2nd query: 0.0008 seconds 

,并在页面加载:

UPDATE `online_users` 
SET `last_seen` = CURRENT_TIMESTAMP 
WHERE `user_id` = '$user_id' 

的时代变迁到这里!

这是为什么?我的猜测是,它与表锁定有关,但我不知道足够确定或知道更多细节。

+0

第二个查询是否仍然返回正确的结果? –

+1

如果你运行没有第一个查询的第二个查询是否更快?这可能是某种类型的I/O问题 - 我对MySQL内部没有兴趣,但不应该是那种在SQL意义上阻塞的事情,毕竟它是在同一个事务中的同一个连接上,在这种情况下,可以看到未提交的更改或更改已经提交。你在使用InnoDB还是MyISAM? –

+0

@Cade Roux如果我单独运行第二个查询,它会更快,但只需要0.0004分钟。我正在使用MyISAM。 – TK123

回答

1

因为SELECT *包括last_seen MySQL无法缓存查询或子查询。您可以尝试明确列举所有字段,但是last_seen。在InnoDB表

(但一个单独的表online_users使多大意义。)

+0

只是通过显式调用除last_seen之外的所有列名称来尝试它,并且查询时间仍然是相同的长度。 – TK123

+0

所以我们比较聪明;只需更新同一个表即可删除该表的_all_高速缓存的查询数据。或者像每个表的线程分配和更新的磁盘回写那样的含糊不清。 –

-4

查询比对的MyISAM慢。 表中的更多行使查询更慢。 表上的错误索引使查询更慢,请使用EXPLAIN命令进行检查。

0

假设SELECT查询在测试之前运行了好几次,您可能会看到查询缓存的效果。表上的任何更新都会使缓存无效,并强制重新执行查询。通过更新不同的表格,您可以避免破坏这些缓存条目。

+0

这是有道理的,但在我的情况下,我有这个查询只执行一次,这是更新查询后。 – TK123

+0

请注意,您可以在运行任何其他命令之前使用'SET SESSION query_cache_type = OFF;'确认此事。 (这只会禁用当前连接的查询缓存。) –

相关问题