java高效去重

发布于 2024-08-23 14:52:56 字数 101 浏览 11 评论 0原文

假设您有一个很大的文本文件。每行包含一个电子邮件 ID 和一些其他信息(比如一些产品 ID)。假设文件中有数百万行。您必须将此数据加载到数据库中。如何有效地重复数据删除(即消除重复数据)?

Lets say you have a large text file. Each row contains an email id and some other information (say some product-id). Assume there are millions of rows in the file. You have to load this data in a database. How would you efficiently de-dup data (i.e. eliminate duplicates)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

城歌 2024-08-30 14:52:57

疯狂的行数

  • 使用 Map&Reduce 框架(例如 Hadoop)。这是一种成熟的分布式计算,因此除非您拥有 TB 级的数据,否则它就有点过大了。 ( j/k :) )

无法容纳内存中的所有行

  • 即使结果也容纳不下:使用合并排序,将中间数据保存到磁盘。合并时,您可以丢弃重复项(可能是 此示例有帮助)。如果需要的话,这可以是多线程的。
  • 结果将适合:您可以使用行迭代器或其他东西并不断添加到此 HashSet 中,而不是读取内存中的所有内容然后将其放入 HashSet 中(见下文)。您可以使用 ConcurrentHashMap 并使用多个线程来读取文件并添加到此 Map。另一个多线程选项是使用 ConcurrentSkipListSet。在这种情况下,您将实现compareTo()而不是equals()/hashCode()(compareTo()==0表示重复)并继续添加到此SortedSet。

适合内存

  • 设计一个保存数据的对象,实现一个好的 equals()/hashCode() 方法,并将它们全部放入 HashSet 中。
  • 或者使用上面给出的方法(尽管您可能不想持久保存到磁盘)。

哦,如果我是你,我无论如何都会对数据库施加唯一约束......

Insane number of rows

  • Use Map&Reduce framework (e.g. Hadoop). This is a full-blown distributed computing so it's an overkill unless you have TBs of data though. ( j/k :) )

Unable to fit all rows in memory

  • Even the result won't fit : Use merge sort, persisting intermediate data to disk. As you merge, you can discard duplicates (probably this sample helps). This can be multi-threaded if you want.
  • The results will fit : Instead of reading everything in-memory and then put it in a HashSet (see below), you can use a line iterator or something and keep adding to this HashSet. You can use ConcurrentHashMap and use more than one thread to read files and add to this Map. Another multi-threaded option is to use ConcurrentSkipListSet. In this case, you will implement compareTo() instead of equals()/hashCode() (compareTo()==0 means duplicate) and keep adding to this SortedSet.

Fits in memory

  • Design an object that holds your data, implement a good equals()/hashCode() method and put them all in a HashSet.
  • Or use the methods given above (you probably don't want to persist to disk though).

Oh and if I were you, I will put the unique constraint on the DB anyways...

烟酉 2024-08-30 14:52:57

我将从显而易见的答案开始。创建一个哈希图,并将电子邮件 ID 作为键,将其余信息放入值(或创建一个对象来保存所有信息)。当您到达新行时,检查该键是否存在,是否移动到下一行。最后使用 HashMap 写出所有 SQL 语句。我确实同意 eqbridges 的观点,即如果您有“无数”行,那么内存限制将很重要。

I will start with the obvious answer. Make a hashmap and put the email id in as the key and the rest of the information in to the value (or make an object to hold all the information). When you get to a new line, check to see if the key exists, if it does move to the next line. At the end write out all your SQL statements using the HashMap. I do agree with eqbridges that memory constraints will be important if you have a "gazillion" rows.

‘画卷フ 2024-08-30 14:52:57

您有两个选择,

  1. 用 Java 实现:您可以将诸如 HashSet 之类的东西放在一起进行测试 - 如果集合中不存在每个项目,则为每个项目添加电子邮件 ID。

  2. 在数据库中执行:在表上放置唯一约束,这样dups就不会添加到表中。这样做的一个额外好处是,您可以重复该过程并从以前的运行中删除重复项。

You have two options,

  1. do it in Java: you could put together something like a HashSet for testing - adding an email id for each item that comes in if it doesnt exist in the set.

  2. do it in the database: put a unique constraint on the table, such that dups will not be added to the table. An added bonus to this is that you can repeat the process and remove dups from previous runs.

我不会写诗 2024-08-30 14:52:57

看看 Duke (https://github.com/larsga/Duke) 快速重复数据删除和记录用java编写的链接引擎。它使用Lucene进行索引并减少比较次数(以避免不可接受的笛卡尔积比较)。它支持最常见的算法(编辑距离、jaro winkler 等),并且具有极强的可扩展性和可配置性。

Take a look at Duke (https://github.com/larsga/Duke) a fast dedupe and record linkage engine written in java. It uses Lucene to index and reduce the number of comparison (to avoid the unacceptable Cartesian product comparison). It supports the most common algorithm (edit distance, jaro winkler, etc) and it is extremely extensible and configurable.

允世 2024-08-30 14:52:57

不能通过电子邮件和产品 ID 为表建立索引吗?然后按索引读取应该可以通过顺序读取轻松识别电子邮件或电子邮件+prodId 的重复项,并简单地匹配先前的记录。

Can you not index the table by email and product ID? Then reading by index should make duplicates of either email or email+prodId readily identified via sequential reads and simply matching the previous record.

川水往事 2024-08-30 14:52:57

您的问题可以通过提取、转换、加载 (ETL) 方法来解决:

  • 您将数据加载到导入模式中;
  • 对数据进行您喜欢的各种转换;
  • 然后将其加载到目标数据库模式中。

您可以手动执行此操作或使用 ETL 工具。

Your problem can be solve with a Extract, transform, load (ETL) approach:

  • You load your data in an import schema;
  • Do every transformation you like on the data;
  • Then load it into the target database schema.

You can do this manually or use an ETL tool.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文