关于在jdbc中使用多线程的教程

时间:2011-08-25 07:31:29

标签: java multithreading jdbc

我们公司有一个每天运行的批处理应用程序,它主要执行一些与数据库相关的工作,例如从文件中将数据导入数据库表。

该应用程序中定义了20多个任务,每个任务可能依赖于其他任务。 应用程序逐个执行任务,整个应用程序在一个线程中运行。

完成所有任务需要3~7个小时。我认为它太长了,所以我想也许我可以通过多线程来提高性能。

我认为由于任务之间存在依赖关系,因此并行运行任务并不好(或者说并不容易),但也许我可以使用多线程来提高任务内部的性能。

例如:我们有一个定义为“ImportBizData”的任务,它将数据从数据文件复制到数据库表中(通常包含100,0000多行)。我想知道是否值得使用多线程?

正如我对多线程知之甚少,我希望有人提供一些有关此主题的教程链接。

7 个答案:

答案 0 :(得分:21)

多线程会提高您的表现,但您需要了解以下几点:

  1. 每个线程都需要自己的JDBC连接。线程之间不能共享连接,因为每个连接也是一个事务。
  2. 偶尔以块和commit上传数据,以避免累积大量回滚/撤消表。
  3. 将任务分成几个工作单位,每个单位完成一项工作。
  4. 详细说明最后一点:目前,您有一个任务,它可以读取文件,解析它,打开JDBC连接,进行一些计算,将数据发送到数据库等等。

    你应该做什么:

    1. 一个(!)线程来读取文件并从中创建“作业”。每份工作都应该包含一个小而不是太小的“工作单元”。将这些推入队列
    2. 下一个线程等待队列中的作业并进行计算。当步骤#1中的线程等待慢速硬盘返回新的数据行时,可能会发生这种情况。此转换步骤的结果将进入下一个队列
    3. 通过JDBC上传数据的一个或多个线程。
    4. 第一个和最后一个线程非常慢,因为它们受I / O限制(硬盘速度慢,网络连接更差)。另外,在数据库中插入数据是一项非常复杂的任务(分配空间,更新索引,检查外键)

      使用不同的工作线程可以带来很多好处:

      1. 分别测试每个线程很容易。由于它们不共享数据,因此无需同步。队列将为您做到这一点
      2. 您可以快速更改每个步骤的线程数以调整性能

答案 1 :(得分:5)

多线程可能会有所帮助,如果线路不相关,您可以启动两个进程,一个读取偶数行,另一个不均匀的行,并从连接池(dbcp)获取数据库连接并分析性能。但首先我要调查jdbc是否是最好的方法,通常数据库已经为这样的导入优化了解决方案。这些解决方案还可以临时切换对表的约束检查,并在以后将其重新打开,这对性能也很有帮助。一如既往地视您的要求而定。

此外,您可能需要签出专为批处理而设计的弹簧批。

答案 2 :(得分:0)

据我所知,JDBC Bridge使用同步方法序列化对ODBC的所有调用,因此使用mutliple线程不会给你任何性能提升,除非它提升你的应用程序本身。

答案 3 :(得分:0)

我对JDBC的熟悉程度并不是很高,但关于你的问题的多线程位,你应该记住的是并行处理依赖于有效地将你的问题分成彼此独立的位,并以某种方式将它们放在一起回到一起(他们的输出)。如果你不知道任务之间的潜在依赖关系,你可能最终会在代码中出现奇怪的错误/异常。更糟糕的是,它可能都没有任何问题地执行,但结果可能与真实值不同。多线程是一项棘手的业务,在某种程度上有趣的学习(至少我是这么认为),但当事情向南发展时,脖子上会感到痛苦。

以下是一些可能有用的链接:

如果你真的想努力进入多线程,我可以推荐GOETZ,BRIAN:JAVA CONCURRENCY,真是太棒了。

祝你好运

答案 4 :(得分:0)

我有一个类似的任务。但就我而言,所有表格都彼此无关。

STEP1: 使用SQL Loader(Oracle)将数据上传到数据库(非常快)或任何类似的数据库批量更新工具。

STEP2: 在不同的线程(针对不相关的任务)和单个线程中运行每个上载过程以执行相关任务。

P.S。您可以在应用程序中识别不同的相互关联的作业,并将它们分组;并在不同的线程中运行每个组。

为您提供帮助的链接:

JAVA Threading 按照上面链接中的最后一个示例(示例:使用多个线程对大型任务进行分区)

SQL Loader can dramatically improve performance

答案 5 :(得分:0)

我发现将大量记录插入Oracle的最快方法是使用数组操作。请参阅“setExecuteBatch”方法,该方法特定于OraclePreparedStatement。它在这里的一个例子中描述: http://betteratoracle.com/posts/25-array-batch-inserts-with-jdbc

答案 6 :(得分:0)

如果多线程会使您的工作复杂化,您可以使用Async消息传递。我不完全清楚你的需求是什么,所以,以下是我目前所看到的。

  1. 创建一个文件阅读器java,其目的是读取biz文件并将消息放入服务器上的JMS队列。这可能是带有静态void main()
  2. 的普通Java
  3. 在消息驱动的bean中使用JMS消息(如果你有多个服务器,那么你可以设置池中创建的bean数限制,50或100,具体取决于需要)你的工作现在拆分为多个服务器。
    1. 每行数据在每台服务器上的2台服务器和50个bean之间异步分配。
  4. 您不必在整个过程中处理线程,JMS是理想的,因为您的数据在事务中,如果在您向服务器发送ack之前出现故障,则消息将重新发送给消费者,负载将在服务器之间进行拆分,而不需要像多线程那样做任何特殊操作。

    此外,春天提供春季批次,可以帮助你。 http://docs.spring.io/spring-batch/reference/html/spring-batch-intro.html#springBatchUsageScenarios