我正在使用MySQL处理一个包含四列(两个varchar、一个int和一个key)的大型日志文件(大约3亿条记录),但这需要很长时间。
其目标是挖掘日志文件,并找到正在以较高频率执行某个操作的记录。
在高于任意事件ID的事件期间状态为a或U的记录。我正在使用GROUP BY将它们插入一个新的表中,这需要一整天以上的时间来运行。有没有一种方法可以更快地做到这一点?
INSERT INTO `tbl_FrequentActions`(`ActionCount`, `RecordNumber`)
SELECT
COUNT(`idActionLog`) as 'ActionCount',
`RecordNumber`
FROM `ActionLog`
WHERE (`ActionStatus` like 'D' or `ActionStatus` like 'U') AND
`EventID` > 103
GROUP BY `RecordNumber`
HAVING COUNT(`idActionLog`) > 19
;
使用临时表分别运行WHERE参数是否更快。比如创建临时表,在我运行组之前把所有东西都切掉?
ActionLog中的所有字段都被索引。
编辑:所有数据已经在一个表的日志数据库中。刚才有人提到我在那一点上模棱两可。
索引对列是独立的。
编辑2:
有人问我的日志文件缓冲区是否为这种大小的文件正确配置,这是一个很好的问题,但我不知道。是的,它是InnoDB格式的。
我建立了一个包含数百万条记录的测试表,并在上面运行查询。花了1分30秒。我将查询分解为使用一个临时表来处理所有where子句,然后对临时表逐组运行查询。把时间缩短到一分钟以内。所以可以节省几个小时。
编辑3:
我可以用“重复更新”来加快速度吗?我试过了,但它一直在跑。我认为这是笛卡尔错误。我需要给这些桌子起个别名吗?
INSERT INTO `tbl_FrequentActions`(`ActionCount`, `RecordNumber`)
SELECT
'1' as 'ActionCount',
`RecordNumber`
FROM `ActionLog`
WHERE (`Status` like 'D' or `Status` like 'U') AND
`EventID` > 103
ON DUPLICATE KEY UPDATE
`DeliveryCount` = (`DeliveryCount` + 1)
;
最佳答案
这听起来像是数据仓库应用程序的“标准”摘要表。我将陈述几个假设,然后讨论如何做到这一点。结果查询可能需要一个小时;可能只需要几分钟。
ActionLog很大,但它只是“添加”到。您从不UPDATE
或DELETE
数据(除了老化旧数据)。
“任意事件ID”实际上是更常规的东西,例如“某天的开始”。
首先,您需要将300万行中的大部分汇总到摘要表中。然后,每天(或每小时?)在此基础上,总结出新的数据——这是一个相当快速的操作。或者,也可以使用IODKU。在决定哪个之前,我们需要了解插入ActionLog的频率。(可能很快)日志条目是成批的吗?还是一次一个?
然后,将对摘要表执行“report”查询,并比对“Fact”表(ActionLog)运行快得多。
典型的汇总表的工作方式是EventDate >= '2018-04-01'
而不是EventID > 103
。所以,我需要一些帮助来理解“103”是从哪里来的。Status
有多少不同的值?我们需要在拥有多行和拥有多列之间做出决定。
为了进一步了解我的未来:
Summary Tables和High speed ingestion