2016-11-21 67 views
6

我遇到以下问题。 我使用和API连接到某个地方,并获取数据作为输入流。 的目标是在删除重复行后保存数据。 第10,15,22列定义的重复。在大型数据库中删除java中的重复项

我使用多个线程获取数据。 目前我首先将数据保存到csv文件中,然后删除重复项。 我想在阅读数据时做到这一点。 数据量约为1000万条记录。 我有限的内存,我可以使用。该机器有32GB的内存,但我有限,因为有其他应用程序使用它。

我在这里读到了关于使用哈希映射。 但我不确定我有足够的内存来使用它。

有没有人有建议如何解决这个问题?

+1

您是否有API的输出示例?是由三列(10,15,22)的组合定义的重复,还是每一列都必须是唯一的,而不涉及其他列? –

+0

api的输出是类似于这样的字符串: =“banna”,=“orange”,=“apple”...等约30个元素。 这些列的组合是关键。 – mikeP

回答

0

您可以使用ConcurrentHashSet。它会自动删除重复的元素,它的线程安全性达到一定的限制

+0

什么是内存限制? 它会处理我拥有的数据量吗? – mikeP

1

一个HashMap将占用至少与原始数据一样多的内存。因此,对于您的数据集的大小可能不太可行(但是,您应该检查它,因为如果它是最简单的选项)。

我会做的是将数据写入文件或数据库,计算要进行重复数据删除的字段的哈希值,并将哈希值存储在内存中,并对文件进行适当的引用(例如,where的字节索引原始值在文件中)。当然应该尽可能小。

当您点击哈希匹配时,查找原始值并检查它是否相同(因为不同值的哈希值可能会一起出现)。

现在的问题是你期望有多少重复。如果你期望几场比赛,我会选择一个便宜的写作和昂贵的阅读解决方案,即将所有东西线性地转储到一个平面文件中并从该文件中读回。

如果你期望很多匹配,它可能是相反的方式,即有一个索引文件或一组文件,甚至是一个数据库(确保它是一个数据库,写操作不是太昂贵)。

+0

如果我散列键并将其插入列表(或链表),并检查列表是否存在散列,如果不存在,我将直接写入目标文件,如果存在,我会忽略? 我除了有大约200万个独特的记录。 – mikeP

+0

正如@lexicore所提到的那样,您可能有散列冲突,即两个不同的值可能具有相同的散列。如果你可以为你的用例提供一个特殊的散列函数来保证避免散列冲突,那么你可以做你所描述的。否则,一旦你找到一个相同的散列,你必须比较实际的基础值。 一个例外将是一个用例,其中可以接受一些独特的条目(一种相当不寻常的情况)。 –

1

的解决方案取决于有多大的15列10,你的数据,22

假设它不是太大(比如,约1KB),实际上你可以实现一个内存解决方案。

  • 实现一个Key类从15个列10,存储值,22.小心地实施equalshashCode方法。 (您也可以使用正常的ArrayList。)
  • 创建一个Set,它将包含您读取的所有记录的密钥。
  • 对于您阅读的每条记录,请检查它是否已在该集合中。如果是,请跳过该记录。如果不是,写入记录输出,将密钥添加到集合中。确保您以线程安全的方式进行设置。

在最糟糕的情况下,您需要number of records * size of key内存量。对于10000000个记录和假设的<每个密钥1kb,这应该在10GB左右工作。

如果密钥大小仍然过大,您可能需要一个数据库来存储密钥集。

另一种选择是存储密钥的散列而不是全部密钥。这将需要更少的内存,但你可能会得到散列冲突。这可能会导致“误报”,即错误的重复,这些重复实际上并不重复。为了完全避免这种情况,你需要一个数据库。