这是我的代码
void fixInstellingenTabel(object source, ElapsedEventArgs e)
{
NASDataContext _db = new NASDataContext();
List<Instellingen> newOnes = new List<Instellingen>();
List<InstellingGegeven> li = _db.InstellingGegevens.ToList();
foreach (InstellingGegeven i in li) {
if (_db.Instellingens.Count(q => q.INST_LOC_REF == i.INST_LOC_REF && q.INST_LOCNR == i.INST_LOCNR && q.INST_REF == i.INST_REF && q.INST_TYPE == i.INST_TYPE) <= 0) {
// There is no item yet. Create one.
Instellingen newInst = new Instellingen();
newInst.INST_LOC_REF = i.INST_LOC_REF;
newInst.INST_LOCNR = i.INST_LOCNR;
newInst.INST_REF = i.INST_REF;
newInst.INST_TYPE = i.INST_TYPE;
newInst.Opt_KalStandaard = false;
newOnes.Add(newInst);
}
}
_db.Instellingens.InsertAllOnSubmit(newOnes);
_db.SubmitChanges();
}
基本上,InstellingGegevens表格由另一台服务器的某些程序填充。 我需要做的是检查此表中是否有新记录,并在Instellingens中填写新记录。
此代码在15k记录上运行4分钟。我该如何优化它?或者是存储过程的唯一方式吗?
此代码在计时器中运行,每6小时运行一次。如果存储过程最好,如何在计时器中使用它?
Timer Tim = new Timer(21600000); //6u
Tim.Elapsed += new ElapsedEventHandler(fixInstellingenTabel);
Tim.Start();
答案 0 :(得分:3)
在存储过程中执行此操作会快得多。我们做了一些非常相似的事情,表中只有大约10万件物品,它每五分钟更新一次,并且里面有更多的字段。我们的工作大约需要两分钟才能运行,然后它会在三个数据库的多个表中进行更新,因此您的工作只需要几秒钟。
您需要的查询就像:
create procedure UpdateInstellingens as
insert into Instellingens (
INST_LOC_REF, INST_LOCNR, INST_REF, INST_TYPE, Opt_KalStandaard
)
select q.INST_LOC_REF, q.INST_LOCNR, q.INST_REF, q.INST_TYPE, cast(0 as bit)
from InstellingGeven q
left join Instellingens i
on q.INST_LOC_REF = i.INST_LOC_REF and q.INST_LOCNR = i.INST_LOCNR
and q.INST_REF = i.INST_REF and q.INST_TYPE = i.INST_TYPE
where i.INST_LOC_REF is null
您可以从SQL服务器中的作业运行该过程,而不涉及任何应用程序,或者您可以使用ADO.NET从您的计时器执行该过程。
答案 1 :(得分:2)
您可以优化此方法的一种方法是将Count(...) <= 0
更改为Any()
。但是,更好的优化是在单个查询外部循环中检索此信息:
var instellingens = _db.Instellingens
.Select(q => new { q.INST_LOC_REF, q.INST_LOCNR, q.INST_REF, q.INST_TYPE })
.Distinct()
.ToDictionary(q => q, q => true);
(第二个想法,HashSet
在这里最合适,但遗憾的是没有ToHashSet()
扩展方法。如果您愿意,可以自己编写一个!)
然后在你的循环中:
if (instellingens.ContainsKey(new { q.INST_LOC_REF, q.INST_LOCNR,
q.INST_REF, q.INST_TYPE })) {
// There is no item yet. Create one.
// ...
}
然后你可以通过使它变为lazy-retrieve来优化循环本身:
// No need for the List<InstellingGegeven>
foreach (InstellingGegeven i in _db.InstellingGegevens) {
// ...
}
答案 2 :(得分:1)
Guffa说的话,但如果你的表现与你所追求的一样,那么在这里使用Linq并不是最好的方法。与所有其他ORM一样,Linq牺牲了可用性。对于典型的应用程序执行路径,这通常是一个很好的权衡。另一方面,SQL非常非常擅长基于集合的操作,因此真的是在这里飞行的方式。