从多个线程的单个数据库表中获取数据的最佳方法?

时间:2010-12-23 11:32:07

标签: java multithreading database-design jdbc

我们有一个系统,我们每秒都会收集有关多个网站上用户活动的数据。我们将数据转储到数据库X(比如MS SQL Server)。我们现在需要从daatbase X中获取此单个表中的数据并插入数据库Y(比如mySql)。

我们希望通过多个线程从数据库X获取基于时间的数据,以便我们尽可能快地获取。一旦获取并存储在数据库Y中,我们将从数据库X中删除数据。

这种设计是否有最佳实践?任何特定的事情要照顾桌面设计,如分享或什么?还有其他我们需要注意的事项,以确保我们尽可能快地从多台机器上运行的线程中获取它吗?

提前致谢! 拉维

4 个答案:

答案 0 :(得分:1)

如果要将数据从一个数据库移动到另一个数据库,则通过让多个线程完成工作,您将无法获得任何优势。它只会增加争用。

如果两个数据库的类型相同,那么您应该查看供应商特定的复制工具。这基本上总是优于自己开发的解决方案。

如果数据库不同(供应商),则必须确定

的有效机制
  1. 识别新的/更新/删除的行(触发器,基于范围的查询,完全转储)
  2. 传输数据(卸载到文件和FTP,从程序中拉/推)
  3. 将数据加载到其他数据库(导入,批量插入)
  4. 没有更多细节,就不可能比这更具体。 哦,影响你选择的两个最重要的考虑因素是:

    1. 预期的数据量是多少?
    2. 源数据库中的行创建与目标数据库中的可用性之间的最长可接受延迟

答案 1 :(得分:0)

我会测试(通过测量)你的假设,即多个slurper线程会加快速度。在您的问题中没有更具体,看起来您希望对数据库执行ETL(提取转换加载)过程,当您让数据库特定技术处理它时,这些非常有效,特别是如果您对聚合等感兴趣

答案 2 :(得分:0)

您的问题有两个级别:

  1. 这两个数据库之间的交易:

    这很重要,因为您将从源数据库中删除数据库。您必须确保仅在数据库成功存储到Y时从X中删除数据。另一方面,您必须确保从X中删除数据必须成功,以防止将相同数据重新插入Y.

  2. 传输数据的表现:

    如果X数据库每当有一个在线数据库时都有传入数据,那么只收集数据,存储到Y并删除它们并不是一个好习惯。规划批量大小,程序启动该批次的交易;重复运行程序,直到X中的数据数量小于批量。

  3. 在这两个数据库中,您应该添加一个表来记录批处理以进行处理。 处理中有三种状态。

    INIT - The start of batch, this value should be synchronized between two databases
    COPIED - In database Y, the insertion of data and the update of this status should be in one transaction.
    FINISH - In database X, the deletion of data and the update of this status should be in on transaction.
    

    当编程运行时,它首先检查“INIT”或“COPIED”状态的批次,然后重新启动要处理的会话。

    • 如果X有“INIT”记录且Y没有,只需将相同的INIT记录插入Y,然后执行插入Y.
    • 如果Y中的记录为“COPIED”且X为“INIT”,则只需将X的状态更新为“COPIED”,然后执行删除操作。
    • 如果X中的记录为“FINISH”且Y中的相应记录为“COPIED”,则只需将Y的状态更新为“FINISH”。

    总之,批处理数据可以让您有机会优化两个数据库之间的转移。批量大小决定了转换效率,取决于两个因素:其他操作同时使用这些数据库的方式以及数据库的调整参数。在一般情况下,Y的写入吞吐量可能是处理的瓶颈。

答案 3 :(得分:0)

线程不是要走的路。数据库是这里的瓶颈。多个线程只会增加争用。即使10个进程将数据阻塞到SQL Server中,单个线程(而不是很多)也可以更快地将其拉出。毫无疑问。

SELECT本身会导致主表中的锁定,从而降低INSERT的吞吐量,因此我会尽快“进入并退出”。如果是我,我会:

  1. 根据范围查询(日期,recno,等等)选择行,将它们转储到文件中,然后关闭结果集(光标)。
  2. 根据相同的范围查询删除行。
  3. 然后处理转储。如果可能,转储格式应该适合批量加载到MySQL中。
  4. 我不想打败你的架构,但整体而言设计听起来有问题。从经历高INSERTion速率的表中选择和删除行会产生巨大的锁定问题。我会看着“双缓冲”SQL Server中的数据。

    例如,插件每两分钟在两个表之间切换。例如,在第一分钟INSERT进入TABLE_1,但是当分钟翻转时,它们开始INSERT到TABLE_2,下一分钟返回TABLE_1,依此类推。当INSERTS进入TABLE_2时,从TABLE_1中选择所有内容并将其转储到MySQL中(尽可能高效),然后TRUNCATE表(删除所有行,零罚分)。这样,读者和作者之间永远不会发生锁争用。

    协调TABLE_1和TABLE_2之间的翻转点是棘手的部分。但它可以通过巧妙地使用SQL Server分区视图自动完成。