我有一个表(logs),其中包含以下列(还有其他列,但这些是重要的):
基本上,这是一个事件的记录,该事件一次开始,一次结束。该表当前有几十万行。我希望它会增长到数百万。为了加快查询的速度,我添加了另一列和预先计算的值:
为了计算结束时间,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。
注意,在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。换句话说,这可能是您可以使用此特定查询进行操作的程度,尽管解决表存储格式的根本不同的查询或方法可能仍然更有效。
| 归档时间: |
|
| 查看次数: |
12423 次 |
| 最近记录: |