0

我有一个查询,用于通过聚合进行汇总。

该表称为“连接”,大约有 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
4

3 回答 3

1

我建议您在以下位置创建一个复合索引(app_id, time_started_dt)

ALTER TABLE connections ADD INDEX(app_id, time_started_dt)
于 2013-07-11T16:34:39.597 回答
1

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

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

注意:创建索引可能需要几个小时,并且该操作将阻止在运行时对表进行插入/更新/删除。

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

由于此表中有大量行,您可能还需要考虑分区。

于 2013-07-11T16:38:02.510 回答
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;
于 2015-02-20T13:54:05.907 回答