5

我正在运行一个简单的 MySQL 查询来查找用户玩游戏的总时间:

SELECT userId, SUM(time) AS totalGameTime
                    FROM game_attempts
                    WHERE userId = 19599

EXPLAIN 显示以下内容:

id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra
1  SIMPLE  game_attempts  ref  userId_gameId  userId_gameId  4  const  26880  

PROFILER 显示,大部分时间都花在“发送数据”上:

Sending data    1.786524

为什么这么简单的查询需要这么长时间才能完成?在哪里寻找瓶颈?

更新。时间是 INT(11) 字段,不涉及转换。

更新。可能的解决方案是引入 (userId, time) 索引,通过将部分数据移动到索引树来解决问题。但它并没有解决更大的问题,即为什么总结 30000 个整数需要这么长时间。

这个问题没有一个简单的答案。指数是正确的,不涉及耗时的转换。这只是关于数据库引擎调整——为什么定位这 30000 条记录和检索数据需要这么多时间?

重要的是要说该表使用 InnoDB 引擎并包含大约 200 万条记录。

4

6 回答 6

1

它表明您正在向客户端返回大量行。可以加吗

GROUP BY userId

以确保您只返回一行?

于 2013-07-30T09:37:48.170 回答
1

尝试像这样为 userId 创建索引将解决您的问题:

   ALTER TABLE game_attempts ADD INDEX (userId);
于 2013-07-30T09:24:53.727 回答
0

好的,我注意到这是一个 anwser,所以你不能再犯这个错误

从 MySQL 5.0.23 开始,您可以设置

ONLY_FULL_GROUP_BY by SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY ';

您正确配置服务器

mysql> SELECT name, MAX(age) FROM t;
ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)
with no GROUP columns is illegal if there is no GROUP BY clause

来源(http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_only_full_group_by

于 2013-08-14T22:09:48.607 回答
0

您的“时间”列过于精确?如果求和怎么办

SEC_TO_TIME(SUM(TIME_TO_SEC(time)))

反而?

于 2013-07-30T10:36:02.683 回答
0

在 userId 上创建索引。这限制了对用户 ID 失败的记录的访问。

于 2013-07-30T09:18:25.107 回答
0

在几乎任何其他 DBMS 中,您的语句将被视为无效 SQL,因为查询的选择部分包含一个聚合函数以及一个不属于 GROUP BY 子句的字段 - 事实上,您没有 GROUP BY 子句.

Oracle eg 会告诉你:

ORA-00937: 不是单组组函数

你会在 MSSQL 中得到类似的东西。我猜 MySQL 在这里所做的是比需要更频繁地计算 SUM 方式。

以下查询将更符合 SQL 标准,并且速度更快:

SELECT userId, SUM(time) AS totalGameTime
  FROM game_attempts
 WHERE userId = 19599
GROUP BY userId;
于 2013-07-30T09:46:25.107 回答