2011-03-01 110 views
1

我有一个表(logs)具有以下列(还有其他的,但这些都是重要的):MySQL的:日期范围内优化记录查询

  • ID(PK,INT)
  • 时间戳(日期时间)(指数)
  • 持续时间(INT)

基本上这是用于启动的时间和在时间结束的事件的记录。这张表目前有几十万行。我预计它会增长到数百万。在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秒。我怀疑这个速度与我要得到它的速度一样快,但我想我会问在这里是否有人提出改进此查询性能的任何想法。

任何建议将是最有帮助的。感谢您的时间。

编辑:我有索引时间戳和结束时间。

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" 

当我运行我的日志表分析,它说的状态确定。

+0

你有什么索引? '说明你的查询的输出是什么?你有[分析](http://dev.mysql.com/doc/refman/5.1/en/analyze-table.html)'logs'表吗? – outis 2011-03-01 22:44:25

+0

@outis,谢谢你的问题。我已将这些信息添加到我的帖子底部。 – Brad 2011-03-01 23:40:04

+0

分析更多的是它对查询优化器如何使用索引的影响。现在我很好奇扩展查询计划是用于查询的,特别是查看查询是否以及如何重写。你会在'EXPLAIN EXTENDED'查询后发布'SHOW WARNINGS'的结果吗? – outis 2011-03-02 00:21:20

回答

4

请注意EXPLAIN输出中logs表的连接类型为“ALL”且键为NULL,这意味着将安排全表扫描。 “范围检查每个记录”消息意味着MySQL在logs使用range access method的结果从别的地方检查列值之后。我认为这意味着,一旦dates已经创建,MySQL能够执行远程使用第二和第三个指标(可能是那些在TimestampEndTime),而不是执行全表扫描上logs加入。如果你只对TimestampEndTime指数分别,尝试添加两个指标,这可能会导致更有效的连接类型(例如index_merge而不是range):

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

我相信(虽然很容易被错)查询计划中的其他项目或者不是真正的问题或不能被消除。 filesort,作为后者的一个例子,可能是由于GROUP BY。换句话说,这可能是您可以对此特定查询执行什么操作的程度,尽管针对表格存储格式的完全不同的查询或方法仍可能更有效。

+0

谢谢@outis,这是最有帮助的。我对优化查询不太熟悉,这给了我很多继续。我会对你的建议做更多的研究。与此同时,我想到了一个更有效的方法来做到这一点,将“日志”限制为相关条目,并且一次完成整个过程1天。我将在以后每天在应用程序上分别运行这些查询,并将数据插入表中供以后使用。我会尽快发布我最后的结果,但我现在无法得到它。我认为我的ISP关闭了我的服务器,呵呵。 – Brad 2011-03-02 00:51:24

+0

@Brad:如果你还没有,请务必阅读[查询执行计划(MySQL文档http://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html )。我的回答是基于该部分的信息。 – outis 2011-03-02 01:13:39

2

你可以看看merge tables用来加快处理。通过合并表,由于表被拆分,索引更小,导致更快的读取。另外,如果您有多个处理器,搜索可以并行进行,从而提高性能。