从多个线程的单个数据库表中获取数据的最佳方法?
我们有一个系统,我们每秒都会在多个网站上收集用户活动的数据。我们将这些数据转储到数据库X(比如MS SQL Server)中。我们现在需要从daatbase X中的单个表中获取数据并插入数据库Y(比如说mySql)。从多个线程的单个数据库表中获取数据的最佳方法?
我们希望通过多线程从数据库X中获取基于时间的数据,以便尽可能快地获取数据。一旦提取并存储在数据库Y中,我们将从数据库X中删除数据。
这种设计是否有任何最佳实践?任何具体的事情要照顾桌子设计,如分享或什么?是否还有其他任何事情需要注意,以确保我们可以从运行在多台机器上的线程中尽可能快地获取它?
提前致谢! Ravi
我会测试(通过测量)你的假设,多个slurper线程将加快速度。没有更具体的问题,它看起来像你想用你的数据库做一个ETL(提取转换加载)过程,当你让数据库特定的技术处理它时,这些是非常有效的,特别是如果你有兴趣在聚合等
感谢您的回复。让我试着让这个更清楚,我会设置多台机器,每台机器运行4个“fetcher”线程。所有这些多线程将从一个数据库表中获取数据,并将其转储到这个新的数据库中以备将来处理。我们的目标是尽可能快地从原始数据库获取数据,然后清除它。其他一些软件将继续生成这些数据并继续在原始数据库中发布。 – 2010-12-23 13:57:16
我以前使用ETL的东西,但更多的是作为一夜之间/计划的工作。我想这取决于第一个数据库的填充速度有多快,并且存在任何约束,以及您想将它移动到其他位置?有聚合吗?你为什么要保留原来的“清晰”? – Toby 2010-12-23 17:21:09
如果您将数据从一个数据库移动到另一个数据库,您将不会因多个线程执行工作而获得任何优势。它只会增加争用。
如果两个数据库的类型相同,则应该查看供应商特定的复制工具。这基本上总是胜过本土解决方案。
如果数据库是不同的(供应商),你必须在一个有效的机制来决定
- 确定新的/更新/删除的行(触发器,基于范围查询,完全转储)
- 运输数据(卸载到文件& FTP,拉从程序/推)
- 加载其他数据库上的数据(进口,批量插入)
没有更多细节,这是不可能的比这更具体。 哦,而影响您选择的两个最重要的考虑因素是:
- 预期的数据量是多少?在目标DB源DB行创建和可用性之间
- 最长可接受的延迟
有您的问题的关注的两个层次:
-
这两个数据库之间的交易:
这很重要,因为您会从源数据库中删除数据库。必须确保只有在数据库已成功存储到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是“INIT”,只需将X的状态更新为“COPIED”,然后执行X的删除即可。
- 如果X中的记录是“FINISH”且Y中的相应记录是“COPIED”,只需更新Y的状态为“完成”。
总之,批量处理数据会让您有机会优化两个数据库之间的这种传输。批量大小的数量决定了转换的效率,并取决于两个因素:其他操作同时使用的数据库以及数据库的调整参数。在一般情况下,Y的写吞吐量可能是处理的瓶颈。
线程是不是要走的路。数据库是这里的瓶颈。多线程将只有增加争用。即使有10个进程将数据干扰到SQL Server,单个线程(而不是多个进程)可以更快地将其拉出。这绝对没有疑问。
SELECT本身可能会导致主表中的锁定,从而降低INSERT的吞吐量,因此我会尽可能快地“进出”。如果是我,我会:
- 根据范围查询(date,recno,whatever)选择行,将它们转储到文件中并关闭结果集(游标)。
- 根据相同的范围查询删除行。
- 然后处理转储。如果可能的话,转储格式应该可以批量加载到MySQL中。
我不想殴打你的架构,但总的来说设计听起来有问题。选择和删除表中的行高INSERTion率会导致巨大的锁定问题。我将在SQL Server中查看“双缓冲”数据。
例如,每分钟插入在两个表格之间切换。例如,在第一分钟INSERT进入TABLE_1,但是当分钟翻转时,他们开始INSERT到TABLE_2,下一分钟回到TABLE_1等等。当INSERT进入TABLE_2时,选择TABLE_1中的所有内容并将其转储到MySQL(尽可能高效),然后对表进行TRUNCATE(删除所有行,并且零惩罚)。这样,读者和作者之间就不会存在争执。
协调TABLE_1和TABLE_2之间的翻转点是棘手的部分。但它可以通过巧妙使用SQL Server分区视图自动完成。
为什么不从第一个数据库导出数据并将其导入到第二个数据库? – 2010-12-23 12:30:14