我有一个非常慢的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;
用于以下表格结构
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`);
该表包含大约8000万条记录,但需要大约一分钟才能运行。一旦缓存就可以了。
unit_id包含大约3000个不同的随机数,part_id高达10,通道高达3。
反正有加速吗?
分区会有帮助吗?
答案 0 :(得分:2)
假设unit_id
的分布均匀,那么在80米记录中选择一个特定的(3000)将留下超过25k的记录进行检查。
由于您没有进一步的索引来协助,MySQL当前必须检索并检查这些25k记录中的每一条记录,以确定它们是否与剩余的过滤条件匹配。
添加composite索引(即在多列上定义的索引)可以帮助您 - MySQL可以进一步减少需要检查的记录。但是,由于基数较低,part_id
和channel
可能无济于事。目前尚不清楚time
可能存在哪种基数,但这可能是一个很好的起点:
CREATE INDEX unit_time ON function_logger (unit_id, time)
你也可以添加其他过滤列(但要注意time
应该是最后一个,因为你正在搜索范围) - 但是,索引中的列越多,写入的列越慢。表将成为(索引文件和内存占用量将越大)。
最快的读取性能将来自covering索引:
CREATE INDEX covering ON function_logger (
unit_id, part_id, channel, time, function
)
答案 1 :(得分:0)
尝试/测试不同的索引时执行说明并比较结果。 USE INDEX将帮助您测试不同的索引,在select语句中添加该提示(请记住不要使用qc)。
set profiling = on;
select * from function_logger;
show profiles;
show profile for query N;