[英]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;
用於以下表格結構
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個。
反正有加速的嗎?
分區會有所幫助嗎?
假設unit_id
分布均勻,然后在80m條記錄中選擇特定的一項(從3000條中選擇),則您有超過25k條記錄需要檢查。
由於您沒有進一步的索引幫助,MySQL當前必須檢索並檢查這25k條記錄中的每條記錄,以確定它們是否與其余過濾條件匹配。
添加復合索引(即在多個列上定義的復合索引)將在這里為您提供幫助-MySQL可以進一步減少它需要檢查的記錄。 但是,由於基數很低, part_id
和channel
可能無濟於事。 目前尚不清楚,從可能存在什么樣的基數的time
,但是這可能是一個很好的起點:
CREATE INDEX unit_time ON function_logger (unit_id, time)
您也可以添加其他過濾器列(盡管要注意time
應該倒數,因為您正在搜索一個范圍)—但是,索引中的列越多,寫入表的速度就越慢(並且越大索引文件和內存占用量)。
最快的讀取性能將通過覆蓋指數獲得:
CREATE INDEX covering ON function_logger (
unit_id, part_id, channel, time, function
)
嘗試/測試不同的索引時,請執行解釋並比較結果。 USE INDEX將幫助您測試不同的索引,並在select語句中添加該提示(請不要使用qc)。
set profiling = on;
select * from function_logger;
show profiles;
show profile for query N;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.