SQL Server CE 应用程序中独特的记录插入最佳做法
本文关键字:插入 记录 最佳 CE Server 应用程序 SQL | 更新日期: 2023-09-27 18:30:15
数据库引擎应该完成所有工作,还是应该由客户端应用程序负责检查唯一性?
我正在用 C# 开发一个应用程序来扫描驱动器并将文件信息存储在 SQL Server CE 数据库中,我想知道哪种方式确保唯一条目是"最佳"。到目前为止,我尝试了以下三种方法,并且没有看到性能有任何差异:
- 维护集合对象
- 检查数据库中是否存在
- 依赖于数据库中的唯一索引
我的三种方法的伪代码。实际代码将文件分解为多个部分,并使用多个表来存储路径、扩展名、卷/服务器和其他信息,以及索引记录来查找数据。
collectionObj //initialize with existing records from database
While (filesToAdd.Count > 0 )
{
file = filesToAdd.Dequeue();
If(!collectionObj.Contains( file.Name ))
{
Insert file.Name into database
collectionObj.Add(file.Name)
}
}
使用方法 1,我认为在内存中搜索对象会更快,但由于 SQL Server CE 数据库也在内存中,因此我不太确定其好处。
While (filesToAdd.Count > 0 )
{
file = filesToAdd.Dequeue();
if( ( select count(*) from database where filename = file.Name) == 0 )
{
Insert file.Name into database
}
}
方法 2 不使用任何额外的对象/内存,但会大量查询数据库以查找重复项。使用 SQL Server CE 网络流量不是问题,但过多的查询必须对性能产生影响。
While (filesToAdd.Count > 0 )
{
file = filesToAdd.Dequeue();
try
{
Insert file.Name into database
}catch(Duplicate index violation exception)
{
//do nothing
}
}
我倾向于方法 3,主要是因为它简化了代码,但它似乎懒惰地成为最佳实践。同样在重复插入时,数据库会抛出错误,程序也是如此。这似乎会影响性能。
给定所提供的信息,当您知道会有很多重复项时,哪种是将大量信息添加到数据库中的"最佳"方法?如果数据主要是唯一的还是主要是重复的,答案会改变吗?如果你有更好的方法,那么我想到的我会很高兴听到它。我的问题专门针对SQL Server CE,它不具有SQL Server的全部功能,请在提供建议时牢记这一点。
答案是 . . .在数据库中执行此操作。
唯一性要求是数据的要求。 应使用数据库来强制实施这些要求。
请记住,确保唯一条目需要对insert
和update
进行测试。 而且,您希望将唯一性作为数据完整性的一部分。 因此,无论更新或插入如何完成(通过应用程序、手动、通过触发器或其他方式),您都希望进行检查。 保证始终完成的唯一方法是在数据库中执行检查。
这个论点超越了性能。 但是,假设唯一索引适合内存,数据库在性能检查方面应该非常有效。 在某些情况下,性能可能非常重要,以至于将在应用程序中检查约束。 这些将很少而且相距甚远。 而且,我可能会质疑为什么将数据库用于此类应用程序的数据存储。
正确答案像往常一样,这取决于。让数据库这样做的"懒惰"解决方案最终是正确的答案。但是,如果可以筛选出客户端上的重复项,并且筛选掉的时间和精力有足够的好处来防止数据库执行所有筛选,那么在客户端上进行筛选是有意义的。您仍将对数据库强制实施唯一性,但您可以通过筛选出客户端上的某些或大多数重复项来卸载其某些处理。如果我从实际应用经验中知道值得付出努力,我可能只会走这条路。
为什么懒惰的好方法会是一个坏方法?
如果您打算使用数据库来存储数据,并且希望确保没有重复的条目,那么当然应该将 UNIQUE 约束引入您的行。它不仅可以帮助您维护无重复的数据存储,而且还将为您提供识别每一行的好方法。
如果存在重复条目,数据库引擎将在插入数据库时注意到这一点,并抛出您很容易捕获的错误/异常。
显然,您希望数据库处理唯一约束,但听起来您希望避免在尝试插入重复记录时引发的异常。通常,我建议在SQL INSERT语句中使用If NOT EXIST,但你不能用SQL Server Compact做到这一点。
另一个技巧可能是先尝试 UPDATE,如果没有行受到影响,您就知道该记录不存在,您可以安全地插入它。这是一点额外的工作,但如果你期待很多重复项,它可能仍然比捕获所有这些异常更有效。
在尝试将已知重复项放入数据库之前尝试过滤掉它们也可能是明智的。也许可以考虑使用 HashSet 来跟踪您在该会话期间已插入的唯一 ID。如果某个值在您的 HashSet 中,您知道您可以跳过它并节省对数据库的调用。