我正在使用Parallel.ForEach
在Oracle DB上执行一些工作,我从日志中看到它没有将负载分成N个块,其中N = MaxDegreeOfParallelism
。这是预期的,因为每个块可能需要更长或更短的时间来处理,但是块确实将工作负载分成太小。 ODP.NET由于某种原因,如果打开了池(ORA-12518),则会使用开放连接使DB过载,因此我禁用了它。这消除了错误,但我想减少打开和关闭连接所花费的时间。
有没有办法影响Parallel.ForEach
将工作量分成更大的块?
作为参考,这是代码目前的样子:
//conn is the primary connection stored in the object
logger.Report("Started");
var allObjects = GetObjects(); //uses the primary connection
logger.Report(string.Format("Retrieved {0} objects", allObjects.Count));
var i = allObjects.Count;
var taskID = 0;
Parallel.ForEach(
allObjects,
new ParallelOptions { MaxDegreeOfParallelism = 16, },
() => {
var c = (DbConnection)((ICloneable)conn).Clone();
c.Open();
var t = Interlocked.Increment(ref taskID);
logger.Report(string.Format("Task #{0} started", t));
return (conn: c, task: t);
},
(o, loopState, c) => {
try {
var objectName = o.Name;
var objectType = o.Type;
logger.Report(string.Format("Retrieving {0} {1}", objectType, objectName));
var dbObject = GetObject(c.conn, o.Name, o.Type);
logger.Report(string.Format("Processing {0} {1}", objectType, objectName));
var result = ProcessObject(dbObject);
logger.Report(string.Format("Recompiling {0} {1}", objectType, objectName));
ProcessResult(c.conn, result);
logger.Report(string.Format("{0} objects remaining", Interlocked.Decrement(ref i)));
return c;
} catch (Exception ex) {
logger.Report("ERROR: " + ex);
throw;
}
},
c => {
logger.Report(string.Format("Task #{0} finished", c.task));
c.conn.Close();
c.conn.Dispose();
});
logger.Report("Recompiling invalids...");
RecompileInvalids(); //uses the primary connection
logger.Report("Done");
答案 0 :(得分:0)
结果是将Max Pool Size=24;Connection Timeout=60;
添加到连接字符串比尝试重新分区列表更好。