数据库引擎是否应该完成所有工作,或者检查唯一性的责任是否应由客户端应用程序负责?
我正在用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的全部功能,请在提供建议时牢记这一点。
答案 0 :(得分:1)
答案是。 。 。在数据库中进行。
唯一性要求是数据的要求。应该使用数据库来强制执行这些要求。
请记住确保要求对insert
和update
进行测试的唯一条目。而且,您希望将唯一性作为数据完整性的一部分。因此,无论更新或插入的执行方式如何(通过应用程序,手动,通过触发器等),都希望检查发生。保证始终完成的唯一方法是在数据库中进行检查。
这个论点超越了表现。但是,假设唯一索引适合内存,数据库在性能检查方面应该非常高效。在某些情况下,性能至关重要,应在应用程序中检查约束。这些将是少之又少。而且,我可能会质疑为什么数据库被用于这种应用程序的数据存储。
答案 1 :(得分:0)
为什么懒惰的好方法会成为一种糟糕的方法?
如果您打算使用数据库来存储数据,并且您希望确保没有重复的条目,那么当然应该为您的行设置UNIQUE约束。它不仅可以帮助您维护无重复的数据存储,还可以为您提供识别每一行的好方法。
如果有重复的条目,数据库引擎会在插入数据库时注意到这一点,并抛出一个你很容易捕获的错误/异常。
答案 2 :(得分:0)
正确答案与往常一样,取决于。拥有数据库的“懒惰”解决方案最终是正确的答案。但是,如果您可以在客户端上过滤掉重复项,并且过滤掉的时间和精力有足够的好处,以防止数据库执行所有过滤,那么在客户端上进行过滤是有意义的。您仍将在数据库上强制执行唯一性,但您可以通过过滤掉客户端上的某些或大多数重复项来卸载其某些处理。如果我从实际的应用经验中知道这是值得的,我可能只会走这条路。
答案 3 :(得分:0)
显然,您希望数据库处理唯一约束,但听起来您希望避免在尝试插入重复记录时抛出的异常。通常,我建议在SQL INSERT语句中使用IF NOT EXISTS,但不能使用SQL Server Compact。
另一个技巧可能是首先尝试UPDATE,如果没有行受影响,你知道记录不存在,你可以安全地插入它。这是一些额外的工作,但如果你期望有很多重复,它可能仍然比捕获所有这些例外更有效。
在尝试将它们放入数据库之前尝试过滤掉已知的重复项也是明智之举。也许考虑使用HashSet来跟踪您在该会话期间已插入的唯一ID。如果一个值在你的HashSet中,你知道你可以跳过它并自己保存对数据库的调用。