非常慢的简单 mysql 查询

Very slow simple mysql query

我有一个非常慢的 mysql 查询如下:

SELECT function,  CONVERT_TZ(`time`, '+01:00','+01:00') 
FROM `function_logger` 
WHERE unit_id=3067785 
  and part_id=3 and channel=0  
  and `time` > NOW()-INTERVAL 1 DAY 
order by time;

以下 table 结构

CREATE TABLE IF NOT EXISTS `function_logger` (
  `id` int(11) NOT NULL,
  `unit_id` int(11) NOT NULL,
  `part_id` tinyint(4) NOT NULL DEFAULT '0',
  `channel` tinyint(4) NOT NULL DEFAULT '0',
  `function` tinyint(11) NOT NULL,
  `time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `function_logger`
  ADD PRIMARY KEY (`id`),
  ADD KEY `unit_id` (`unit_id`);

table 包含大约 8000 万条记录,但 运行 大约需要一分钟。一旦缓存就可以了。

unit_id 包含大约 3000 个不同的随机数,part_id 最多 10 个,通道最多 3 个。

有没有办法加快速度?

分区有帮助吗?

假设 unit_id 的均匀分布,然后从 8000 万条记录中选择一个特定的(3000 条),您将有超过 25000 条记录需要检查。

由于您没有进一步的索引可以提供帮助,MySQL 当前必须检索并检查这 25k 条记录中的每一条记录,以确定它们是否符合剩余的过滤条件。

添加 composite 索引(即在多列上定义的索引)会在此处帮助您 — MySQL 从而可以进一步减少需要检查的记录。但是,由于基数如此之低,part_idchannel 可能帮不上什么忙。目前尚不清楚 time 可能存在哪种基数,但这可能是一个很好的起点:

CREATE INDEX unit_time ON function_logger (unit_id, time)

您也可以添加其他过滤列(但请注意 time 应该排在最后,因为您要在其上搜索范围)——但是,索引中的列越多,写入速度越慢table 将变为(索引文件和内存占用量将越大)。

最快的读取性能将从 covering 索引获得:

CREATE INDEX covering ON function_logger (
  unit_id, part_id, channel, time, function
)

当trying/tesing个不同的索引执行解释并比较结果。 USE INDEX 将帮助您测试不同的索引,在 select 语句中添加该提示(切记不要使用 qc)。

set profiling = on;

select * from function_logger;
show profiles;
show profile for query N;