这可能不是您关于 RegEx 性能下降的问题的直接答案——这有点令人着迷。但是 - 在阅读了上面的所有评论和讨论之后 - 我建议以下内容:
解析一次数据,将匹配的数据拆分到数据库表中。看起来您正在尝试捕获以下字段:
Player_Name | Monetary_Value
如果您要创建每行包含这些值的数据库表,然后在创建时捕获每个新行 - 解析它 - 并附加到数据表 - 您可以轻松地对数据进行任何类型的分析/计算- 无需一次又一次地解析 25M 行(这是一种浪费)。
此外 - 在第一次运行时,如果您要将 25M 记录分解为 100,000 个记录块,然后运行算法 250 次(100,000 x 250 = 25,000,000) - 您可以享受您所描述的所有性能而不会减速,因为你把工作分块了。
换句话说 - 考虑以下几点:
创建数据库表如下:
CREATE TABLE PlayerActions (
RowID INT PRIMARY KEY IDENTITY,
Player_Name VARCHAR(50) NOT NULL,
Monetary_Value MONEY NOT NULL
)
创建一个算法,将 25m 行分解为 100k 块。使用 LINQ / EF5 作为假设的示例。
public void ParseFullDataSet(IEnumerable<String> dataSource) {
var rowCount = dataSource.Count();
var setCount = Math.Floor(rowCount / 100000) + 1;
if (rowCount % 100000 != 0)
setCount++;
for (int i = 0; i < setCount; i++) {
var set = dataSource.Skip(i * 100000).Take(100000);
ParseSet(set);
}
}
public void ParseSet(IEnumerable<String> dataSource) {
String playerName = String.Empty;
decimal monetaryValue = 0.0m;
// Assume here that the method reflects your RegEx generator.
String regex = RegexFactory.Generate();
for (String data in dataSource) {
Match match = Regex.Match(data, regex);
if (match.Success) {
playerName = match.Groups[1].Value;
// Might want to add error handling here.
monetaryValue = Convert.ToDecimal(match.Groups[2].Value);
db.PlayerActions.Add(new PlayerAction() {
// ID = ..., // Set at DB layer using Auto_Increment
Player_Name = playerName,
Monetary_Value = monetaryValue
});
db.SaveChanges();
// If not using Entity Framework, use another method to insert
// a row to your database table.
}
}
}
运行上述一次以加载所有预先存在的数据。
在某处创建一个钩子,允许您检测新行的添加。每次创建新行时,调用:
ParseSet(new List<String>() { newValue });
或者如果一次创建多个,请调用:
ParseSet(newValues); // Where newValues is an IEnumerable<String>
现在,您可以从数据中进行任何计算分析或数据挖掘,而不必担心超过 2500 万行的动态性能。