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

Bra*_*rad 2 mysql

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

  • id(PK,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`;
Run Code Online (Sandbox Code Playgroud)

请注意,数字表严格用于轻松枚举日期范围。它是具有一列的表number,并且包含值1、2、3、4、5等。

这正好为我提供了我想要的东西...带有4列的表格:

  • 日期
  • 总计(在当前时间点之外开始和结束的总行)
  • 新的(在此时间点开始的行)
  • 掉线(在此时间点结束的行)

问题是,此查询可能要花费大量时间才能执行。要经过120秒(如查询中所示),大约需要10秒。我怀疑这大约与我将要获得的速度一样快,但是我想在这里问是否有人对提高此查询的性能有任何想法。

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

编辑:我有时间戳和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"
Run Code Online (Sandbox Code Playgroud)

当我在日志表上运行分析时,状态为OK。

out*_*tis 5

注意,在EXPLAIN输出中,logs表的联接类型为“ ALL”,键为NULL,这表示已计划进行全表扫描。“范围检查每个记录”消息意味着MySQL使用多种接入方式logs的结果从别的地方检查列值之后。我的意思是,一旦dates创建了MySQL,就可以logs使用第二和第三个索引(可能是Timestamp和上的索引)执行远程联接,EndTime而不是执行全表扫描。如果只有索引Timestamp和索引EndTime分别存在,请尝试在两个索引上都添加索引,这可能会导致更有效的联接类型(例如index_merge而不是range):

CREATE INDEX `start_end` ON `logs` (`Timestamp`, `EndTime`);
Run Code Online (Sandbox Code Playgroud)

我相信(尽管可能很容易出错)查询计划中的其他项不是真正关心的问题,还是无法消除。作为后者的示例,文件排序可能是由于引起的GROUP BY。换句话说,这可能是您可以使用此特定查询进行操作的程度,尽管解决表存储格式的根本不同的查询或方法可能仍然更有效。