我面临与Big Performance Problems With Oracle DataReader in .Net类似的问题。我的存储过程在两个查询上使用union all(每个查询都使用一些连接)。总之,SP在10秒内返回大约20K的记录。看起来没问题。
但是,我面临着应用程序方面的问题,其中dataReader.Read()大约需要四分钟才能获取这些数据。以下是我目前使用的代码:
List<int> ordinalIndexes = new List<int>();
foreach (string headerName in headerColumnMapping.Keys)
ordinalIndexes.Add(dataReader.GetOrdinal(headerColumnMapping[headerName].ToString()));
while (dataReader.Read())
{
foreach (var ordinalIndex in ordinalIndexes)
csvString.AppendFormat("\"{0}\"{1}", dataReader[ordinalIndex].ToString().Trim(), separator);
}
我发现dataReader.Read()中有很多块,它们很容易安静地处理(不到一毫秒)。但是,还有更多需要10-35秒(一次读取)。
我试过了:
对此有任何建议都很高兴。
答案 0 :(得分:1)
无法测试您的数据,但可以在循环中添加一些优化 例如,不要格式化每个单独的字段,而是格式化整行。
您可以尝试将此代码调整为您的数据
string separator = ";";
int pos = 0;
string format = "";
// Prepare the format mask for the whole records
foreach (string headerName in headerColumnMapping)
{
format += "\"{" + pos + "}\"" + separator;
pos++;
}
// Remove the last separator and add a newline
format = format.Substring(0, format.Length - 1) + "\r\n";
// Create the array of the field positions
var range = Enumerable.Range(0, reader.FieldCount);
// Set an initial capacity for the string builder to 10MB
// Of course this could be a waste of memory if you plan to retrieve
// small amounts of data.
StringBuilder csvString = new StringBuilder(1024*1024*10);
while (dataReader.Read())
{
var x = dataReader as IDataRecord;
// Create the array of the field values
var k = range.Select(r => x[r].ToString()).ToArray();
// Append the whole line
csvString.AppendFormat(format, k);
}
上面的代码从datareader中检索所有字段。如果只想检索通过 ordinalIndexes 列表映射的某些字段,则只需删除范围的创建,然后使用当前代码准备要检索的整数列表。然后将 range.Select 替换为 ordinalIndexes.Select
另一个小东西,但有大量的支出是定义StringBuilder的容量,特别是如果你希望检索大量的数据。如果立即定义足够大的初始容量,则可以避免在缓冲区填满时重新分配内存。
但是,如果您尝试导出CSV文件,我建议您查看一些专门创建CSV文件的库。如果你有更好的表现,你可能会检查它们。
答案 1 :(得分:0)
通过优化存储过程解决了我的问题。我添加了一些索引(基于SP中的查询),整体性能在很大程度上得到了改善。
感谢@Steve提供有关应用程序级别更改的输入。虽然,就我而言,数据库性能是真正的罪魁祸首。