C# 如何使用SQL CE加速LINQ插入?
历史 我有一个“记录”(3500)列表,我将其保存为XML,并在程序退出时进行压缩。自:C# 如何使用SQL CE加速LINQ插入?,c#,.net,linq,optimization,sql-server-ce,C#,.net,Linq,Optimization,Sql Server Ce,历史 我有一个“记录”(3500)列表,我将其保存为XML,并在程序退出时进行压缩。自: 记录的数量增加了 只有大约50条记录需要在退出时更新 节省大约需要3秒钟 我需要另一个解决方案——嵌入式数据库。我选择SQL CE是因为它可以与VS一起工作,没有任何问题,而且许可证对我来说还可以(我将它与Firebird、SQLite、EffiProz、db4o和BerkeleyDB进行了比较) 数据 记录结构:11个字段,其中2个为主键(nvarchar+字节)。其他记录包括字节、数据时间、双精度和
- 记录的数量增加了
- 只有大约50条记录需要在退出时更新
- 节省大约需要3秒钟
foreach (var entry in dict.Entries.Where(it => it.AlteredByLearning))
{
PrimLibrary.Database.Progress record = null;
record = new PrimLibrary.Database.Progress();
record.Text = entry.Text;
record.Direction = (byte)entry.dir;
db.Progress.InsertOnSubmit(record);
record.Status = (byte)entry.LastLearningInfo.status.Value;
// ... and so on
db.SubmitChanges();
}
原始操作
SqlCeCommand cmd=conn.CreateCommand()
cmd.CommandText=“进度”;
cmd.CommandType=System.Data.CommandType.TableDirect;
SqlCeResultSet rs=cmd.executesultset(ResultSetOptions.updateable)
我对此不是很肯定,但似乎应该在循环之外进行
db.SubmitChanges()
调用。也许这会加快速度?在每笔交易中做更多的工作。
对于典型的关系数据库,提交通常是非常昂贵的操作,因为数据库必须等待磁盘刷新以确保数据不会丢失(以及所有这些)。在这种操作中,没有专用控制器的传统HDD磁盘IO速度非常慢:数据必须刷新到物理磁盘上——在IO同步的情况下,一秒钟可能只有30-60次提交
请参阅SQLite常见问题解答:。忽略不同的数据库引擎,这是完全相同的问题
通常,LINQ2SQL在SubmitChanges
内部创建一个新的隐式事务。要避免此隐式事务/提交(提交是昂贵的操作),请执行以下操作之一:
SubmitChanges
less(比如,一旦超出循环)或using (var ts = new TransactionScope()) {
// LINQ2SQL will automatically enlist in the transaction scope.
// SubmitChanges now will NOT create a new transaction/commit each time.
DoImportStuffThatRunsWithinASingleTransaction();
// Important: Make sure to COMMIT the transaction.
// (The transaction used for SubmitChanges is committed to the DB.)
// This is when the disk sync actually has to happen,
// but it only happens once, not 3500 times!
ts.Complete();
}
但是,使用单个事务或单个SubmitChanges调用的方法的语义不同于上面调用SubmitChanges 3500次并创建3500个不同隐式事务的代码的语义。特别是,原子操作的大小(相对于数据库)不同,可能不适合所有任务
对于LINQ2SQL更新,更改乐观并发模型(例如,禁用乐观并发模型或仅使用时间戳字段)可能会导致性能的微小改进。然而,最大的改进将来自减少必须执行的提交数量
愉快的编码。你能展示一些代码示例吗?@Kevin Pullin,当然,我添加了必要的部分来了解如何在这两种情况下进行插入。你尝试过了吗?@svick,你能解释一下序列化对象与LINQ在这种情况下有什么关系吗?@macias,没什么,但你说保存到XML太慢了。使用
BinaryFormatter
比使用普通的SQL数据库更容易,速度也足够快。似乎您不了解实际数据库的大多数功能,所以更轻的可能更好(甚至更快)。尽管它就在我眼前,我故意忽略了这一点,认为在桌面环境中,这是可以忽略的,因为有两个因素——SQL CE引擎不会每次重新加载,也不会造成连接损失。哦,天哪,我离真相太远了——一次振作起来,我得到的不是5分钟,而是5秒(这比DirectTable慢了一个数量级,但对我来说还行)。谢谢你的冷水浴:-)。
using (var ts = new TransactionScope()) {
// LINQ2SQL will automatically enlist in the transaction scope.
// SubmitChanges now will NOT create a new transaction/commit each time.
DoImportStuffThatRunsWithinASingleTransaction();
// Important: Make sure to COMMIT the transaction.
// (The transaction used for SubmitChanges is committed to the DB.)
// This is when the disk sync actually has to happen,
// but it only happens once, not 3500 times!
ts.Complete();
}