使用8.5亿行优化MySQL表上的聚合

时间:2013-07-11 16:17:30

标签: mysql sql optimization

我有一个查询,我用它来汇总汇总。

该表称为“连接”,大约有8.43亿行。

CREATE TABLE `connections` (
  `app_id` varchar(16) DEFAULT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  `time_started_dt` datetime DEFAULT NULL,
  `device` varchar(255) DEFAULT NULL,
  `os` varchar(255) DEFAULT NULL,
  `firmware` varchar(255) DEFAULT NULL,
  KEY `app_id` (`bid`),
  KEY `time_started_dt` (`time_started_dt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

当我尝试运行查询时,例如下面的查询,它需要超过10个小时,我最终会杀死它。有没有人看到我正在制作的任何错误,对于如何优化查询有任何建议?

SELECT
app_id,
MAX(time_started_dt),
MIN(time_started_dt),
COUNT(*)
FROM
connections
GROUP BY
app_id

3 个答案:

答案 0 :(得分:1)

我建议您在(app_id, time_started_dt)上创建一个综合索引:

ALTER TABLE connections ADD INDEX(app_id, time_started_dt)

答案 1 :(得分:1)

要使该查询执行,您确实需要一个合适的覆盖索引,app_id作为前导列,例如

CREATE INDEX `connections_IX1` ON `connections` (`app_id`,` time_start_dt`);

注意:创建索引可能需要数小时,操作将阻止在表运行时插入/更新/删除表。

EXPLAIN将显示您的查询的建议执行计划。在覆盖索引到位后,您将在计划中看到“使用索引”。 (“覆盖索引”是MySQL可以用来满足查询而无需访问基础表的索引。也就是说,查询可以完全从索引中得到满足。)

如果此表中包含大量行,您可能还需要考虑分区。

答案 2 :(得分:0)

我已经尝试过对随机生成的数据(大约100万行)的查询。添加PRIMATY KEY可将查询性能提高10%。 正如其他人已经建议的那样,复合索引应该添加到表中。索引time_started_dt没用。

CREATE TABLE `connections` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `app_id` varchar(16) DEFAULT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  `time_started_dt` datetime DEFAULT NULL,
  `device` varchar(255) DEFAULT NULL,
  `os` varchar(255) DEFAULT NULL,
  `firmware` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `composite_idx` (`app_id`,`time_started_dt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;