非常慢的简单mysql查询

非常慢的简单mysql查询,mysql,database-partitioning,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 `f

我有一个非常慢的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万条记录,但运行大约需要一分钟。一旦缓存就好了

单元id包含大约3000个不同的随机数,部分id最多10个,通道最多3个

有没有办法加快速度


分区会有帮助吗?

假设单位id的分布是一致的,那么在8000万条记录中选择一条特定的(3000条)记录将使您有超过25k条记录需要检查

由于您没有进一步的索引来帮助,MySQL当前必须检索并检查这些25k记录中的每一条,以确定它们是否符合其余的筛选条件

添加一个索引(即在多个列上定义的索引)将有助于MySQL进一步减少需要检查的记录。然而,由于基数很低,
part\u id
channel
可能没有多大帮助。现在还不清楚从
时代起可能存在什么样的基数,但这可能是一个很好的起点:

CREATE INDEX unit_time ON function_logger (unit_id, time)
您也可以添加其他筛选列(尽管要注意,
time
应该是最后一个,因为您正在搜索一个范围)-但是,索引中的列越多,写入表的速度就越慢(索引文件和内存占用空间也越大)

通过索引可以获得最快的读取性能:


尝试/测试不同索引时,执行解释并比较结果。使用索引将帮助您在select语句中添加该提示来测试不同的索引(记住不要使用qc)


添加覆盖索引
alter table function\u logger Add index search\u idx(单位id、部分id、频道、时间)
将时间从一个时区转换为同一时区有什么意义?@AbhikChakraborty:这不是覆盖索引…@eggyal,系统支持多个时区,这似乎是一个简单的选择。不过,现在我看了一下,对于已经在这个时区的用户来说,添加这些内容是没有意义的。非常感谢。使用覆盖索引,它现在几乎可以立即选择记录。
CREATE INDEX covering ON function_logger (
  unit_id, part_id, channel, time, function
)
set profiling = on;

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