有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

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

提前谢谢! 拉维


共 (3) 个答案

  1. # 1 楼答案

    如果要将数据从一个数据库移动到另一个数据库,那么使用多个线程来完成这项工作将不会带来任何好处。这只会增加争议

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

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

    1. 识别新的/更新的/删除的行(触发器、基于范围的查询、完全转储)
    2. 传输数据(卸载到文件和FTP,从程序中拉/推)
    3. 在另一个数据库上加载数据(导入、批量插入)

    没有更多细节,就不可能比这更具体。 哦,影响你选择的两个最重要的因素是:

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

    您的问题有两个层面的担忧:

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

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

    2. 传输数据的性能:

      如果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的写吞吐量可能是处理的瓶颈

  3. # 3 楼答案

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

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

    1. 根据范围查询选择行(日期、recno等),将其转储到文件中,然后关闭结果集(光标)
    2. 基于同一范围查询删除行
    3. 然后处理转储。如果可能,转储格式应该适合批量加载到MySQL中

    我不想破坏你的架构,但总体来说,这个设计听起来有问题。从插入率较高的表中选择和删除行将产生巨大的锁定问题。我将研究SQL Server中的数据“双缓冲”

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

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