假设您有一个大文本文件。每行包含一个电子邮件 ID 和一些其他信息(比如一些产品 ID)。假设文件中有数百万行。您必须将此数据加载到数据库中。您将如何有效地重复数据删除(即消除重复数据)?
6 回答
疯狂的行数
- 使用 Map&Reduce 框架(例如 Hadoop)。这是一个成熟的分布式计算,所以除非你有 TB 的数据,否则它是一种过度杀伤力。( j/k :) )
无法容纳内存中的所有行
- 甚至结果也不适合:使用归并排序,将中间数据持久化到磁盘。合并时,您可以丢弃重复项(可能此示例有帮助)。如果需要,这可以是多线程的。
- 结果将适合:您可以使用行迭代器或其他东西并继续添加到此 HashSet,而不是读取内存中的所有内容然后将其放入 HashSet(见下文)。您可以使用 ConcurrentHashMap 并使用多个线程来读取文件并添加到此 Map。另一个多线程选项是使用 ConcurrentSkipListSet。在这种情况下,您将实现 compareTo() 而不是 equals()/hashCode()(compareTo()==0 表示重复)并继续添加到此 SortedSet。
适合记忆
- 设计一个保存数据的对象,实现一个好的 equals()/hashCode() 方法并将它们全部放在一个 HashSet 中。
- 或者使用上面给出的方法(虽然你可能不想持久化到磁盘)。
哦,如果我是你,无论如何我都会将唯一约束放在数据库上......
我将从明显的答案开始。制作一个哈希图并将电子邮件 ID 作为键放入,将其余信息放入值中(或制作一个对象来保存所有信息)。当您进入新行时,检查密钥是否存在,是否移动到下一行。最后使用 HashMap 写出所有 SQL 语句。我确实同意 eqbridges 的观点,即如果您有“无数”行,那么内存限制将很重要。
你有两个选择,
用 Java 来做:你可以把类似的东西放在一起
HashSet
进行测试——如果集合中不存在,则为每个进来的项目添加一个电子邮件 ID。在数据库中执行:在表上设置唯一约束,这样就不会将 dups 添加到表中。另一个好处是您可以重复该过程并从以前的运行中删除重复。
看看 Duke ( https://github.com/larsga/Duke ) 一个用 java 编写的快速重复数据删除和记录链接引擎。它使用 Lucene 来索引并减少比较次数(以避免不可接受的笛卡尔积比较)。它支持最常见的算法(编辑距离、jaro winkler 等),并且具有极强的可扩展性和可配置性。
您不能按电子邮件和产品 ID 为表格编制索引吗?然后按索引读取应该可以通过顺序读取轻松识别电子邮件或电子邮件+prodId 的副本,并简单地匹配先前的记录。