带有GROUP BY的MySQL JOIN需要永久运行

时间:2016-02-02 08:42:01

标签: mysql sql

我的数据库中有两个表,如下所示:

ElementRef

users表有大约200,000行,sessions表有大约10m行。我试着做一个简单的JOIN,如下所示:

CREATE TABLE `users` (
  `id` varchar(10) DEFAULT NULL,
  `gender` varchar(9) DEFAULT NULL,
  `age` varchar(5) DEFAULT NULL
  KEY `id` (`id`)
)

CREATE TABLE `sessions` (
  `user_id` varchar(10) DEFAULT NULL,
  `time` int(11) DEFAULT NULL,
  KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

当我运行此查询时,即使LIMIT设置为1,它也会无休止地运行而没有结果。如果我省略GROUP BY子句,它会立即运行。这里有什么我可能会遗漏的,或者只是会话表太大而无法高效工作?

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

首先应该为表添加索引和主键。 建议将users表中的id作为主键,在会话表中添加id列作为主键。您还可以在sessions表的userid列中添加索引。

答案 1 :(得分:0)

在表格上放置适当的索引非常重要,以确保性能。将primarey键放在id和sessions.user_id上的索引上可以大大提高查询运行时间。

另外,对于引用完整性,请考虑使用外键和约束。

如果您的会话数据是临时的(除非您的表充当某种日志并且需要保留数据),请考虑到期/删除不必要的会话条目以最小化该表。是否需要所有10M会话条目?有20万用户,因为他们同时在线,所以活动会话不应超过20万。如果以后需要,您还可以考虑定期将非活动条目移动到另一个表以进行长期存储。例如,这可以在用户结束其会话时立即完成。

话虽如此,一张包含10M条目的表格应该可以正常使用,而且远远没有考虑到#34;太多"在正确建模的数据库上。

答案 2 :(得分:0)

KEY关键字表示两个表中的user_id都有索引,所以看起来没问题。

LEFT JOIN通常比INNER JOIN更耗时。在这种情况下,我建议尝试这样的子查询:

SELECT users.id,
       (SELECT  SUM(time)
          FROM  sessions
          WHERE users.id = sessions.user_id) AS TotalTime,
  FROM users
  LIMIT 1;

此外,您可以问自己是否真的需要知道用户5年前花费的会话时间。最好将其限制在固定的时间段内,例如过去6个月的总会话时间。

您需要在sessions表中添加一列来指定会话的发生时间(日期)。然后你会添加一个过滤器。