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

Java 从具有多个线程的单个数据库表中获取数据的最佳方法?,java,multithreading,database-design,jdbc,Java,Multithreading,Database Design,Jdbc,我们有一个系统,在这个系统中,我们每秒都会收集多个网站上用户活动的数据。我们将数据转储到数据库X中(比如MS SQL Server)。我们现在需要从daatbase X的这个表中获取数据,并插入到数据库Y中(比如说mySql) 我们希望通过多个线程从数据库X获取基于时间的数据,以便尽可能快地获取数据。一旦提取并存储在数据库Y中,我们将从数据库X中删除数据 这种设计有什么最佳实践吗?在桌子的设计上有什么特别需要注意的事情吗,比如分享或者其他什么?我们是否需要注意其他事项,以确保尽可能快地从多台机器

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

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

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

提前谢谢!
Ravi

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

如果您要将数据从一个数据库移动到另一个数据库,让多个线程执行此工作不会获得任何优势。这只会增加争论

如果两个数据库的类型相同,则应该查看供应商特定的复制工具。这基本上总是优于国产解决方案

如果数据库不同(供应商),则必须决定一种有效的

  • 识别新的/更新的/删除的行(触发器、基于范围的查询、完全转储)
  • 传输数据(卸载到文件和FTP,从程序拉/推)
  • 在其他数据库上加载数据(导入、大容量插入)
  • 没有更多的细节,不可能比这更具体。 哦,影响你选择的两个最重要的因素是:

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

  • 您的问题有两个关注级别:

  • 这两个数据库之间的事务:

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

  • 传输数据的性能:

    如果X数据库随时都有传入数据,这是一个在线数据库,那么只收集数据、存储到Y并删除它们不是一个好的做法。计划批量大小时,程序启动该批的事务;重复运行程序,直到X中的数据数小于批处理的大小

  • 在这两个数据库中,您应该添加一个表来记录要处理的批处理。 处理中有三种状态

    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中的记录为“已复制”,而X为“初始化”,则只需将X的状态更新为“已复制”,然后对X执行删除操作
    • 如果X中的记录为“完成”,Y中的相应记录为“复制”,只需将Y的状态更新为“完成”

    总之,批量处理数据将使您有机会优化两个数据库之间的这种传输。批量大小的数量决定转换的效率,并取决于两个因素:这些数据库如何被其他操作并发使用,以及数据库的调整参数。在一般情况下,Y的写入吞吐量可能是处理的瓶颈。

    线程不是解决的办法。数据库是这里的瓶颈。多线程只会增加争用。即使有10个进程将数据塞入SQL Server,单个线程(而不是多个)也可以更快地将数据取出。这是毫无疑问的

    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.
    
    SELECT本身会导致主表中出现锁,从而降低插入的吞吐量,因此我会尽可能快地“进出”。如果是我,我会:

  • 根据范围查询选择行(日期、recno等),将其转储到文件中,然后关闭结果集(光标)
  • 基于同一范围查询删除行
  • 然后处理转储。如果可能,转储格式应该适合批量加载到MySQL中
  • 我不想破坏你的架构,但总体来说,这个设计听起来有问题。从插入率高的表中选择和删除行将产生巨大的锁定问题。我将考虑在SQL Server中对数据进行“双缓冲”

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


    协调表1和表2之间的滚动点是一个棘手的部分。但是,通过巧妙地使用SQL Server分区视图,可以自动完成此操作。

    为什么不从第一个数据库导出数据并导入到第二个数据库中呢?谢谢您的回复。让我试着更清楚地说明这一点,我会设置多台机器运行,比如说4“fetcher”th