检测数据何时发生变化

时间:2010-07-19 07:18:10

标签: database algorithm scalability

好的,所以故事是这样的:

- 我有很多文件(非常大,大约25GB),这些文件采用特定格式,需要在数据存储区中导入

- 这些文件不断更新数据,有时是新的,有时是相同的数据

- 我试图弄清楚如何检测文件中特定行的某些内容是否发生变化的算法,以便最大限度地减少更新数据库所花费的时间

- 它现在的工作方式是我每次都丢弃数据库中的所有数据,然后重新导入它,但这不再适用,因为我需要一个项目更改时间的时间戳

- 文件包含字符串和数字(​​标题,订单,价格等)

我能想到的唯一解决方案是:

- 为数据库中的每一行计算一个哈希值,将其与文件中行的哈希值进行比较,如果它们不同则更新数据库

- 保留2个文件副本,前面的文件和当前文件,并在其上制作差异(这可能比更新数据库更快),并根据这些更新数据库。

由于数据量非常庞大,我现在已经没有选择了。从长远来看,我将摆脱文件,数据将直接推送到数据库,但问题仍然存在。

任何建议,将不胜感激。

4 个答案:

答案 0 :(得分:3)

问题定义已理解

假设您的文件包含

ID,Name,Age
1,Jim,20
2,Tim,30
3,Kim,40

如您所述,可以添加/更新Row,因此文件变为

ID,Name,Age
1,Jim,20    -- to be discarded 
2,Tim,35    -- to be updated
3,Kim,40    -- to be discarded 
4,Zim,30    --  to be inserted 

现在要求通过在两个sql查询中插入/更新2个记录或者包含两个sql语句的1个批处理查询来更新数据库。

  

我在这里做假设

  • 您无法修改现有流程来创建文件。
  • 您正在使用一些批处理[从文件读取 - 在内存中处理 - 在DB中写入] 上传数据库中的数据。

将记录[名称,年龄]的哈希值与ID存储在内存映射中,其中ID是键,值是哈希[如果需要可伸缩性,请使用hazelcast]。

您的Batch Framework加载数据[再次假设将一行文件视为一个记录],需要根据内存Map中的ID检查计算的哈希值。也可以使用批处理框架创建第一次创建用于阅读文件。

 If (ID present)
--- compare hash 
---found same then discard it
—found different create an update sql 
In case ID not present in in-memory hash,create an insert sql and insert the hashvalue

您可以使用spring-batch和hazelcast进行并行处理,块处理和内存中数据分区。

http://www.hazelcast.com/

http://static.springframework.org/spring-batch/

希望这会有所帮助。

答案 1 :(得分:1)

不是为了按需计算数据库中每一行的哈希值,而是为什么不存储哈希值呢?

然后你可以计算相关文件的哈希值,并将其与存储的数据库进行比较。

<强>更新

我想到的另一个选择是将上次修改日期/时间信息存储在数据库中,然后将其与相关文件的信息进行比较。如果无法有意或无意地更改信息,这应该有效。

答案 2 :(得分:1)

无论你使用什么,最糟糕的情况都是O(n),在n~25GB的数据上并不是那么漂亮。

除非您可以修改写入文件的过程。

由于您没有一直更新所有25GB,这是您节省周期的最大潜力。

<强> 1。不要随便写
为什么不进行只写入数据的进程?这样您就可以获得更多数据,但是您将拥有完整的历史记录,并且可以跟踪已处理的数据(已放入数据存储区中的数据)。

<强> 2。如果必须随机写,请保留一份更改清单
或者,如果您真的必须进行随机写入,则可以保留更新行的列表。然后可以在#1中处理此列表,您可以跟踪您处理的更改。如果要保存一些空间,可以保留数据更改的块列表(块是您定义的单位)。

此外,您可以保留更改的块/行的校验和/哈希值。然而,这可能不是很有趣 - 计算起来并不便宜,直接比较可能更便宜(如果你在写作过程中有空闲的CPU周期,可能会节省一些阅读时间,YMMV)。

注意

  • 只有在您可以调整将数据写入磁盘的过程时,#1和#2才有意义
  • 如果您无法修改写入25GB数据的进程,那么我看不到校验和/哈希值如何帮助 - 您必须读取所有数据以计算哈希值(因为您不知道更改了什么) )所以你可以在阅读时直接比较并提出一个行列表来更新/添加(或直接更新/添加)
  • 使用diff算法可能不是最理想的,diff算法不仅会查找更改的行,还会检查给定某些格式选项的两个文本文件之间的最小编辑距离。 (在diff中,这可以用-H或--minimal控制以更慢或更快地工作,即搜索精确的最小解或使用启发式算法,如果iirc此算法变为O(n log n);还不错,但是如果你逐行直接比较,那么你可以使用O(n)慢一点。

答案 3 :(得分:0)

实际上这是一个必须由备份软件解决的问题,为什么不使用他们的一些标准解决方案呢? 最好的方法是挂钩WriteFile调用,这样你就可以在每次更新时收到回调。这对二进制记录非常有用。

我无法理解的东西:文件实际上是文本文件,不只是附加,而是更新?这是非常无效的(连同保留2个文件副本的想法,因为它会使文件缓存工作更糟糕。)