优化数据处理方法的性能
本文关键字:性能 方法 数据处理 优化 | 更新日期: 2023-09-27 18:02:45
我使用以下代码从.txt
文件中获取一些数据(以XML格式-格式不佳),然后在进行一些处理后使用EPPlus将其写入.xlsx
。StreamElements
基本上是改性的XmlReader
。我的问题是关于性能的,我已经做了一些改变,但不知道我还能做些什么。我将把它用于大型数据集,所以我正在尝试修改,使其尽可能高效和快速。任何帮助将不胜感激!
我尝试使用p.SaveAs()
来做excel写作,但它并没有真正看到性能差异。有没有更好更快的写作方法?欢迎提出任何建议。
using (ExcelPackage p = new ExcelPackage())
{
ExcelWorksheet ws = p.Workbook.Worksheets[1];
ws.Name = "data1";
int rowIndex = 1; int colIndex = 1;
foreach (var element in StreamElements(pa, "XML"))
{
var values = element.DescendantNodes().OfType<XText>()
.Select(v => Regex.Replace(v.Value, "''s+", " "));
string[] data = string.Join(",", values).Split(',');
data[2] = toDateTime(data[2]);
for (int i = 0; i < data.Count(); i++)
{
if (rowIndex < 1000000)
{
var cell1 = ws.Cells[rowIndex, colIndex];
cell1.Value = data[i];
colIndex++;
}
}
rowIndex++;
}
}
ws.Cells[ws.Dimension.Address].AutoFitColumns();
Byte[] bin = p.GetAsByteArray();
using (FileStream fs = File.OpenWrite("C:''test.xlsx"))
{
fs.Write(bin, 0, bin.Length);
}
}
}
目前,对于它进行处理,然后将100万行写入Excel工作表,大约需要30-35分钟。
我以前遇到过这个问题,当你逐个修改工作表单元格时,excel有一个巨大的开销。
解决这个问题的方法是创建一个对象数组,并使用WriteRange功能填充工作表。
using(ExcelPackage p = new ExcelPackage()) {
ExcelWorksheet ws = p.Workbook.Worksheets[1];
ws.Name = "data1";
//Starting cell
int startRow = 1;
int startCol = 1;
//Needed for 2D object array later on
int maxColCount = 0;
int maxRowCount = 0;
//Queue data
Queue<string[]> dataQueue = new Queue<string[]>();
//Tried not to touch this part
foreach(var element in StreamElements(pa, "XML")) {
var values = element.DescendantNodes().OfType<XText>()
.Select(v = > Regex.Replace(v.Value, "''s+", " "));
//Removed unnecessary split and join, use ToArray instead
string[] eData = values.ToArray();
eData[2] = toDateTime(eData[2]);
//Push the data to queue and increment counters (if needed)
dataQueue.Enqueue(eData);
if(eData.Length > maxColCount)
maxColCount = eData.Length;
maxRowCount++;
}
//We now have the dimensions needed for our object array
object[,] excelArr = new object[maxRowCount, maxColCount];
//Dequeue data from Queue and populate object matrix
int i = 0;
while(dataQueue.Count > 0){
string[] eData = dataQueue.Dequeue();
for(int j = 0; j < eData.Length; j++){
excelArr[i, j] = eData[j];
}
i++;
}
//Write data to range
Excel.Range c1 = (Excel.Range)wsh.Cells[startRow, startCol];
Excel.Range c2 = (Excel.Range)wsh.Cells[startRow + maxRowCount - 1, maxColCount];
Excel.Range range = worksheet.Range[c1, c2];
range.Value2 = excelArr;
//Tried not to touch this stuff
ws.Cells[ws.Dimension.Address].AutoFitColumns();
Byte[] bin = p.GetAsByteArray();
using(FileStream fs = File.OpenWrite("C:''test.xlsx")) {
fs.Write(bin, 0, bin.Length);
}
}
我没有尝试编译这段代码,所以请仔细检查所使用的索引;并检查任何小的语法错误。
考虑性能的几个额外指针:
- 尝试并行对象数组的填充,因为它主要是基于索引的(可能有一个带有索引跟踪器
Dictionary<int, string[]>
的字典),并在那里查找以更快地填充对象数组。你可能不得不用空间换取时间。 - 看看你是否能够硬编码列和行计数,或者快速计算出来。在我的代码修复中,我设置了计数器来动态计算最大行数和列数;我不建议将其作为永久解决方案。
- AutoFitColumns是非常昂贵的,特别是如果你处理超过一百万行