非常慢的简单mysql查询

时间:2015-09-23 17:04:07

标签: mysql database-partitioning

我有一个非常慢的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。

反正有加速吗?

分区会有帮助吗?

2 个答案:

答案 0 :(得分:2)

假设unit_id的分布均匀,那么在80米记录中选择一个特定的(3000)将留下超过25k的记录进行检查。

由于您没有进一步的索引来协助,MySQL当前必须检索并检查这些25k记录中的每一条记录,以确定它们是否与剩余的过滤条件匹配。

添加composite索引(即在多列上定义的索引)可以帮助您 - MySQL可以进一步减少需要检查的记录。但是,由于基数较低,part_idchannel可能无济于事。目前尚不清楚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;