使用jdbc和mysql并行化查询是否值得?

时间:2015-01-30 12:30:14

标签: java mysql jdbc

一个jdbc"选择"声明需要5秒才能完成。 因此,做5个语句需要25秒。

现在我尝试并行完成这项工作。 db是带有innodb的mysql。 我启动5个线程并为每个线程提供自己的数据库连接。但仍需要25秒才能完成所有工作?

注意我为java提供了足够的堆并且有8个核心但只有一个高清(可能只有一个高清是瓶颈吗?)

这是开箱即用的mysql的预期行为吗? 这是示例代码:

public void doWork(int n) {
        try (Connection conn = pool.getConnection();
             PreparedStatement stmt = conn.prepareStatement("select id from big_table where id between "+(n * 1000000)" and " +(n * 1000000 +1000000));
        ) { 
            try (ResultSet rs = stmt.executeQuery();) {
                while (rs.next()) {
                    Long itemId = rs.getLong("id");
                }
            }
        }
}

public void doWorkBatch() {
    for(int i=1;i<5;i++)
        doWork(i);
}

public void doWorkParrallel() {
    for(int i=1;i<5;i++)
        new Thread(()->doWork(i)).start();
    System.console().readLine();
}

(我不记得在哪里,但我读到标准的mysql安装可以轻松地并行处理1000个连接)

4 个答案:

答案 0 :(得分:3)

这取决于系统中的瓶颈在哪里...... 如果您的查询花费几秒钟建立与数据库的连接,并且只有一小部分实际运行查询,那么您会看到一个很好的改进。 但是如果在mysql中花费时间,运行实际的查询,你就不会看到太大的差异。

我要做的第一件事,不是尝试并发执行,而是优化查询,可能为表添加索引,等等。

答案 1 :(得分:1)

并发执行可能会更快。您还应该考虑批量执行。

答案 2 :(得分:1)

如果有任何并行化的空间,并发执行将有所帮助。在您的情况下,似乎没有并行化的余地,因为您有一个非常简单的查询,它执行大量数据的顺序读取,因此您的瓶颈可能是磁盘传输,然后从服务器到服务器的数据传输客户端。

当我们说RDBMS服务器每秒可处理数千个请求时,我们通常会谈论我们通常在Web应用程序中看到的请求类型,其中每个SQL查询都比您的稍微复杂一些,但会导致更小的磁盘读取(因此它们很可能在缓存中找到)和更小的数据传输(适合网页的东西)。

答案 3 :(得分:1)

看着你的问题,绝对多线程会提高你的表现,因为即使我曾经把4-5小时的批量工作转换成7-10分钟的工作,做的与你想的完全相同,但你需要知道在设计之前跟进事情: -

1)您需要考虑任务间依赖性,即在不同线程上执行的任务。

2)使用连接池是一个好兆头,因为创建数据库连接是Java中的慢进程并且需要很长时间。

3)每个线程都需要自己的JDBC连接。线程之间不能共享连接,因为每个连接也是一个事务。

4)将任务分成几个工作单位,每个单位完成一项工作。

5)特别适用于您的情况,即使用mysql。您使用哪个数据库引擎也会影响性能,因为InnoDB引擎使用行级锁定。这样,它将处理更高的流量。但是,(通常)替代方案(MyISAM)不支持行级锁定,它使用表锁定。 我正在谈论的情况如果另一个线程进来并希望在第一个线程提交之前更新同一行该怎么办。

6)为了提高Java数据库应用程序的性能,使用setAutoCommit(false)运行查询。默认情况下,新的JDBC连接具有自动提交模式ON,这意味着每个单独的SQL语句将在其自己的事务中执行。如果没有自动提交,您可以将SQL语句分组为逻辑事务,可以通过调用commit()或rollback()来提交或回滚。

您还可以查看专为批处理而设计的弹簧批。

希望这有帮助。