我有一个非常慢的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。
还有什么可以加速的吗?
分区有用吗?
发布于 2015-09-23 17:26:23
假设unit_id
的分布是一致的,那么在80m记录中选择一个特定的( 3000)记录就会留下超过25k的记录要检查。
由于您没有进一步的索引可以帮助,MySQL目前必须检索和检查这25k记录中的每一个,以确定它们是否符合剩余的筛选条件。
添加一个https://en.wikipedia.org/wiki/Composite_index_(database)索引(即在多个列上定义的索引)将有助于您在这里工作--MySQL可以进一步减少它需要检查的记录。然而,在基数如此之低的情况下,part_id
和channel
可能没有多大帮助。还不清楚从time
中可能存在什么样的基数,但这可能是一个很好的起点:
CREATE INDEX unit_time ON function_logger (unit_id, time)
您也可以添加其他过滤器列(不过要注意time
应该是最后一个,因为您正在搜索它的范围)-however,索引中的列越多,写入表的速度就越慢(索引文件和内存占用的空间也就越大)。
最快的读取性能将从https://en.wikipedia.org/wiki/Database_index#Covering_index索引中获得:
CREATE INDEX covering ON function_logger (
unit_id, part_id, channel, time, function
)
发布于 2015-09-23 18:59:05
当尝试/测试不同的索引时,执行解释并比较结果。使用索引将帮助您测试不同的索引,在select语句中添加这个提示(记住不要使用qc)。
set profiling = on;
select * from function_logger;
show profiles;
show profile for query N;
https://stackoverflow.com/questions/32745433
复制相似问题