MySQL:优化日期范围内记录的查询

时间:2011-03-01 22:41:08

标签: mysql

我有一个表(logs),其中包含以下列(还有其他列,但这些是重要的列):

  • id(PK,int)
  • 时间戳(日期时间)(索引)
  • 持续时间(int)

基本上,这是一个事件的记录,该事件一次开始并一次结束。该表目前有几十万行。我预计它会增长到数百万。为了加快查询速度,我添加了另一列和预先计算的值:

  • EndTime(日期时间)(索引)

要计算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列的表:

  • 日期
  • 总计(在当前时间点之外开始和结束的总行数)
  • new(此时开始的行)
  • 删除(此时此行结束的行)

问题是,此查询可能需要很长时间才能执行。要经过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时,它表示状态正常。

2 个答案:

答案 0 :(得分:5)

EXPLAIN输出中请注意,logs表的连接类型为“ALL”且密钥为NULL,这意味着将安排全表扫描。 “检查每条记录的范围”消息表示MySQL在检查结果中其他位置的列值后,在logs上使用range access method。我认为这意味着一旦创建dates,MySQL就可以使用第二和第三个索引(logsTimestamp上的索引)在EndTime上执行远程联接而不是执行全表扫描。如果您只分别在TimestampEndTime上添加索引,请尝试在两者上添加索引,这可能会导致更高效的连接类型(例如index_merge而不是range) :

CREATE INDEX `start_end` ON `logs` (`Timestamp`, `EndTime`);

我相信(虽然可能很容易出错)查询计划中的其他项目不是真正关注或无法消除。作为后者的一个例子,filesort可能是由GROUP BY引起的。换句话说,这可能是您使用此特定查询可以执行的操作的范围,尽管解决表存储格式的完全不同的查询或方法仍然可能更有效。

答案 1 :(得分:2)

您可以查看merge tables以加快处理速度。使用合并表,由于表被拆分,索引较小,从而可以更快地获取。此外,如果您有多个处理器,搜索可以并行发生,从而提高性能。