我有一个表(logs
),其中包含以下列(还有其他列,但这些是重要的列):
基本上,这是一个事件的记录,该事件一次开始并一次结束。该表目前有几十万行。我预计它会增长到数百万。为了加快查询速度,我添加了另一列和预先计算的值:
要计算EndTime,我已将Duration
中的秒数添加到Timestamp
字段。
现在我想要做的是运行一个查询,其中结果计算开始(Timestamp
)和结束时间(EndTime
)落在特定时间点之外的行数。然后我想在很长的时间内(比如一年)每隔一秒运行一次这个查询。我还想计算在特定时间点开始的行数,并在特定时间点结束。
我创建了以下查询:
SELECT
`dates`.`date`,
COUNT(*) AS `total`,
SUM(IF(`dates`.`date`=`logs`.`Timestamp`, 1, 0)) AS `new`,
SUM(IF(`dates`.`date`=`logs`.`EndTime`, 1, 0)) AS `dropped`
FROM
`logs`,
(SELECT
DATE_ADD("2010-04-13 09:45:00", INTERVAL `number` SECOND) AS `date`
FROM numbers LIMIT 120) AS dates
WHERE dates.`date` BETWEEN `logs`.`Timestamp` AND `logs`.`EndTime`
GROUP BY `dates`.`date`;
请注意,数字表格仅用于轻松枚举日期范围。它是一个包含一列number
的表,包含值1,2,3,4,5等...
这给了我正是我正在寻找的......一个有4列的表:
问题是,此查询可能需要很长时间才能执行。要经过120秒(如查询中所示),大约需要10秒钟。我怀疑这个速度和我要的速度一样快,但我想我会问这里是否有人提出改善查询性能的想法。
任何建议都会有所帮助。谢谢你的时间。
编辑:我在Timestamp和EndTime上有索引。
我的查询中的EXPLAIN输出:
"id";"select_type";"table";"type";"possible_keys";"key";"key_len";"ref";"rows";"Extra"
"1";"PRIMARY";"<derived2>";"ALL";NULL;NULL;NULL;NULL;"120";"Using temporary; Using filesort"
"1";"PRIMARY";"logs";"ALL";"Timestamp,EndTime";NULL;NULL;NULL;"296159";"Range checked for each record (index map: 0x6)"
"2";"DERIVED";"numbers";"index";NULL;"PRIMARY";"4";NULL;"35546940";"Using index"
当我在我的日志表上运行analyze时,它表示状态正常。
答案 0 :(得分:5)
在EXPLAIN
输出中请注意,logs
表的连接类型为“ALL”且密钥为NULL,这意味着将安排全表扫描。 “检查每条记录的范围”消息表示MySQL在检查结果中其他位置的列值后,在logs
上使用range access method。我认为这意味着一旦创建dates
,MySQL就可以使用第二和第三个索引(logs
和Timestamp
上的索引)在EndTime
上执行远程联接而不是执行全表扫描。如果您只分别在Timestamp
和EndTime
上添加索引,请尝试在两者上添加索引,这可能会导致更高效的连接类型(例如index_merge
而不是range
) :
CREATE INDEX `start_end` ON `logs` (`Timestamp`, `EndTime`);
我相信(虽然可能很容易出错)查询计划中的其他项目不是真正关注或无法消除。作为后者的一个例子,filesort可能是由GROUP BY
引起的。换句话说,这可能是您使用此特定查询可以执行的操作的范围,尽管解决表存储格式的完全不同的查询或方法仍然可能更有效。
答案 1 :(得分:2)
您可以查看merge tables以加快处理速度。使用合并表,由于表被拆分,索引较小,从而可以更快地获取。此外,如果您有多个处理器,搜索可以并行发生,从而提高性能。