非常慢的简单 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_id
和 channel
可能帮不上什么忙。目前尚不清楚 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;
我有一个非常慢的 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_id
和 channel
可能帮不上什么忙。目前尚不清楚 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;