如何在插入之前加快重复检查?
Posted
技术标签:
【中文标题】如何在插入之前加快重复检查?【英文标题】:How can I speed up a dupe check before insert? 【发布时间】:2012-11-18 04:20:19 【问题描述】:我编写了一个实验室处理软件,它接收传入的数据,将其分解,然后将其发送到数据库中的适当字段。 DB表真的很大,字段也很多。在插入数据之前,我会在插入数据之前进行重复检查(我们从多个来源获取重复数据)。
系统通过解析传入数据、填充 linq-to-sql 对象来工作。重复检查通过对 linq-to-sql 对象列表执行 .where 操作来选择尚未在表中的对象。
例如...
input=list (of TableA) 'linq to sql objects
output=input.where(function (x as TableA) not myDb.TableA.any(function(l as table) l.name=x.name, l.dob=x.dob..etc for 10 fields..).tolist
语法有点神秘,但这是我能找到的在 linq 上执行内连接到 sql 对象和数据库记录的唯一方法。在我使用这种方法之前,我逐行执行了重复检查,这要慢得多。
据我了解,Linq 正在将此 linq 语句转换为在服务器上运行的 sql 语句。
我的问题是:有没有办法让它运行得更快?有没有理由期望写出一条 sql 语句来执行重复数据删除和运行传统查询会更快?该语句很慢,但它有效,经过单元测试并阻止了欺骗。我正在寻找更快且相当干净(我知道不难)或更清洁的东西......
【问题讨论】:
虽然不是您问题的直接答案,但我用于类似(尽管不相同)用例的一种技术是编写一个存储过程,该过程执行适当的创建/更新/忽略决策。这会移动所有逻辑服务器端,因此 LINQ 只执行一个 SQL 通信(存储过程调用)。如果您受网络限制,这将有所帮助。 @SAJ14SAJ 我不太明白。 linq 查询不会被转换为传递给服务器的单个 sql 语句吗?我们在一个缓慢的网络上运行,所以如果不是这种情况,那么这可能是阻碍(除了一个大数据库) 简短的回答是:视情况而定。在构造 DataContext 时,您可以通过将TextWriter
传递给 Log
属性来准确了解它在做什么。但根据情况,它可能会在提交插入检查之前进行自己的“此行是否需要更新”检查。您的 where 子句肯定会执行查询,然后 LINQ 总是为每个待处理的插入执行另一个 SQL 命令,一个接一个。网上有很多关于“LINQ sql optimization”查询的信息。
假设这是 SQL Server,我建议您在 SQL Profiler 中捕获 SQL 语句并查看它生成的内容。我怀疑它是在客户端工作,而不是在数据库中,所以我支持 SAJ14SAJ 的建议。
【参考方案1】:
您可以根据名称、dob 和 ... 在表上定义唯一索引。每次插入都可以成功完成或引发唯一约束违规异常。所以在插入之前你不需要任何检查。我认为这是最直接的方法。
【讨论】:
当然适当的索引会有所帮助。 其他人对此有何看法?我认为这是最干净的,因为它 (1) 真正防止了欺骗,并且 (2) 消除了欺骗检查操作 = 更少的代码。另一方面,它会使用错误来指导流量控制——我听说这是不可以的 可以在这里找到关于这个主题的一个很好的讨论:***.com/questions/1736146/…【参考方案2】:如果没有其他进程添加到 SQL 表中,那么您可以在启动程序时将该表读入 HashSet。检查本地 HashSet。如果不在 HashSet 中,则将其添加到 SQL Table 和 HashSet。 HashSet 查找比 SQL 查询快大约 100 倍,即使在同一个物理机器上运行也是如此。我将它用于一些大负载。
如果您只打算在短时间内获得重复数据,那么您可以在开始时跳过从表中加载历史记录或仅加载最后一个 X。检查 HashSet 并且只有在 HashSet 中找不到时才使用 SP插入或跳过。并定期将 HashSet 截断为 X。
【讨论】:
我喜欢这个主意——但桌子可能太大了。回去工作的时候我会玩弄它。 如果表很大,那么只做最后一个 X。如果 HashSet 找到 90% 的配音,那么您已经消除了 90% 的 SQL 的 dup 检查。 “仅加载最后一个 x”是指仅将最后 x 个最近添加的条目加载到表中吗?难道我还不需要检查桌子的其余部分是否有欺骗吗? 我不知道如何比我上次的评论更清楚。如果您在 HashSet 中找到一个 dup,那么您不必检查 SQL。根据重复的实时数据,我假设旧重复的可能性很低,所以如果你检查最后一个 X,你仍然可以捕获最多。以上是关于如何在插入之前加快重复检查?的主要内容,如果未能解决你的问题,请参考以下文章
如何在插入 MySQL 之前检查表中是不是存在名称 [重复]
如何检查html表是不是在js中重复行并对输入求和而不是插入另一行?