我有一个对象数组,我需要根据某些参数从数据库中获取一些对象信息,我正在实现这个:
public IList<object[]> GetRelevants(Registro[] records)
{
List<object[]> returnList = new List<object[]>();
using (var session = SessionFactory.OpenStatelessSession())
{
for (int kr = 0; kr < records.Length; kr++)
{
Registro record = records[kr];
var query = session.QueryOver<Registro>()
.Where(sb => sb.Asunto == record.Asunto)
.And(sb => sb.FechaInicial == record.FechaInicial)
.And(sb => sb.FechaFinal == record.FechaFinal)
.And(sb => sb.FoliosDesde == record.FoliosDesde)
.And(sb => sb.FoliosHasta == record.FoliosHasta)
.And(sb => sb.TomoNumero == record.TomoNumero)
.And(sb => sb.TomoTotal == record.TomoTotal)
.And(sb => sb.SerieCodigo == record.SerieCodigo)
.And(sb => sb.Caja == record.Caja)
.And(sb => sb.Carpeta == record.Carpeta).SelectList(list => list
.Select(p => p.Id)
.Select(p => p.NuevaCaja)
.Select(p => p.NuevaCarpeta)
.Select(p => p.Periodo));
var result = query.SingleOrDefault<object[]>();
returnList.Add(result);
}
}
return returnList;
}
然而,在记录中,有超过10000个项目,因此NHibernate需要大约10分钟才能完成。
有没有办法提高性能呢?
答案 0 :(得分:0)
一个好的解决方案可能是抛弃NHibernate完成此任务并将数据插入临时表,然后加入该临时表。
但是,如果你想使用NHibernate,你可以通过不发出10,000个单独的查询来加快速度(这就是现在正在发生的事情)。您可以尝试将查询分解为合理大小的块:
List<object[]> ProcessChunk(
IStatelessSession session,
int start,
IEnumerable<Registro> currentChunk)
{
var disjunction = Restrictions.Disjunction();
foreach (var item in currentChunk)
{
var restriction = Restrictions.Conjunction()
.Add(Restrictions.Where<Registro>(t => t.Asunto == item.Asunto))
/* etc, calling .Add(..) for every field you want to include */
disjunction.Add(restriction);
}
return session.QueryOver<Registro>()
.Where(disjunction)
.SelectList(list => list
.Select(t => t.Id)
/* etc, the rest of the select list */
.List<object[]>()
.ToList();
}
然后从主循环中调用该方法:
const int chunkSize = 500;
for (int kr = 0; kr < records.Length; kr += chunkSize)
{
var currentChunk = records.Skip(i).Take(chunkSize);
resultList.AddRange(ProcessChunk(session, i, currentChunk));
}
你在这里做的是发出20个(而不是10,000个)查询,看起来像:
select
/* select list */
from
[Registro]
where
([Registro].[Asunto] = 'somevalue' and ... and ... and .. ) or
([Registro].[Asunto] = 'someothervalue' and ... and ... and ... )
/* x500, one for each item in the chunk */
等等。如果500是每个块的大小,则每个查询最多返回500条记录。
这仍然不会很快。我当地的测试将运行时间缩短了一半。
根据您的数据库引擎,您可能会快速运行可以传递的最大数量的参数。您可能需要使用chunkSize
才能使其正常运行。
如果使用临时表并抛弃了NHibernate,你可能会把这个缩短到几秒钟。