我有一个查询,我用它来汇总汇总。
该表称为“连接”,大约有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
答案 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;