如何为数据库批处理作业选择线程数

时间:2018-08-03 02:47:50

标签: java multithreading

我创建了一个批处理作业以从Oracle数据库中提取记录。它正在从JDBC读取记录并写入文件。

但是,处理速度太慢,我想增加编号。线程以执行并行处理。

我已经创建一个队列以存储要处理的记录ID。我将触发多个线程以同时处理记录。

基于记录的总数/线程数以及每条记录要处理的时间,我将能够计算出处理所有记录所需的时间。

但是,如何确定我可以分配的线程数?我相信这是基于CPU内核的数量。我的服务器上有8个CPU内核。

3 个答案:

答案 0 :(得分:3)

Brian Goetz在<Concurrency in Practice>中提供了一个等式:

Nthreads = Ncpu * Ucpu *(1 + W / C)

  • Nthreads是理想的线程数;
  • Ncpu = CPU数量;
  • Ucpu =目标CPU利用率,0 <= Ucpu <= 1;
  • W / C =等待时间与计算时间的比率。

答案 1 :(得分:1)

事实是:这实际上比看起来要难。现实世界中的性能调优远不止要使用固定数量的线程!

首先,仅靠编程来确定有多少个内核并不容易(有关帮助链接的列表,请参阅我的其他answer)。

然后:它也取决于CPU硬件。有些内核只能并行运行一个或两个线程,而其他内核可能可以并行运行4个甚至更多。

当然,您必须了解瓶颈所在。如果您有32个线程试图写入同一io设备,则可能会减慢速度。

长话短说:在您的情况下,当您控制整个堆栈时,您只需进行实验。从另一个答案给出的公式开始。然后测量相关的数字并了解存在哪些影响。

您的后续问题暗示您在这里仍然有些“天真”。当您不了解该公式时,会是什么价值?

我的建议:简单地走,得到其他答案所指的book,然后转到第8.2章,命名调整线程池并开始阅读:

  

线程池的理想大小取决于将要提交的任务的类型以及部署系统的特征。线程池的大小很少应该进行硬编码。而是应通过配置机制提供池大小,或通过咨询Runtime.availableProcessors来动态计算池大小。

     

调整线程池的大小并不是一门精确的科学,但是幸运的是,您只需要避免“太大”和“太小”这两个极端。如果线程池太大,则线程会争用稀缺的CPU和内存资源,从而导致更高的内存使用率和可能的资源耗尽。如果太小,尽管处理器未使用,但吞吐量会受到影响   可用的工作。

     

要正确调整线程池的大小,您需要了解您的计算环境,您的资源预算和任务的性质。部署系统有多少个处理器?多少内存?任务主要执行计算,I / O还是某种组合?它们是否需要稀缺资源,例如JDBC连接?

     

如果您具有不同类别的任务且行为截然不同,请考虑使用多个线程池,以便可以根据其工作负载进行调整。

那么至关重要:

  

对于计算密集型任务,Ncpuprocessor系统通常使用Ncpu +1线程的线程池来实现最佳利用率。

因此,正如已经说明的那样:

  • 这是复杂的东西。您必须知道正在做什么。
  • 因此,您必须对此进行研究。这不是一个可以解释的问题。
  • 另一方面,您不需要计算机科学学位即可获得 working 解决方案。这就是前面提到的 experiments 出现的地方。

答案 2 :(得分:1)

对于数据库代码(例如您的),执行时间将由数据库I / O而不是CPU活动决定。因此在实践中,只有少量线程可以充分利用I / O系统。如果您的数据库很大(我想是这样,那么您就不必担心它的性能了),并且存储在HDD上,则I / O的成本将比CPU处理的成本高得多。该I / O将由一系列依次插入的寻道和顺序I / O组成,而HDD一次只能执行一个操作。搜寻的价格非常昂贵,大型搜寻的价格比小型搜寻的价格高。如果有多个线程在执行I / O,则操作系统将对它们的I / O进行交织,以尝试公平对待每个线程并提供高性能。操作系统可能会使用电梯算法。对I / O使用多个线程会导致要寻找多个位置,因此可以选择在这些位置之间进行较小的寻找。不幸的是,最佳线程数将取决于数据库架构,优化器和您正在执行的查询。如果没有测量的好处,我猜您的查询中每个表大约有一个线程,但是至少有2个线程。