【问题标题】:Inserting Multiple rows in a MySQL Table : Threading vs BatchUpdate在 MySQL 表中插入多行:线程与 BatchUpdate
【发布时间】:2017-11-06 09:39:42
【问题描述】:

假设,我们必须通过java代码在一个mysql表中插入20行。以下哪种方法会有效以及为什么。

1) 使用executeBatch将所有的insert语句变成一个batch,然后使用Preparedstatement的commit方法一次性插入所有行。

2)为每次插入创建线程。每个线程插入一行。

PS:插入是通过web API完成的,所以我们需要实时的状态(是插入失败还是成功)。

【问题讨论】:

  • 我会说 executeBatch 是更好的选择,因为它会在一个 db 调用中进行插入并且性能很高,多线程本身会使这些插入变慢,并且可能来自 DB 池的多个套接字连接被使用,如果你只有一个连接,那么所有其他线程将等待使用该连接。
  • 取决于数据的价值。在某些情况下,当我需要存档某些东西时,当不需要实时数据时,我有一个带有linkedqueue的线程,它确实写入数据库,主线程只需将记录添加到该队列以进行处理。
  • @Marvin 。这是否意味着多线程比第一个选项慢。我需要它实时。
  • 我有单线程来处理顺序插入而不阻塞主进程。

标签: java mysql multithreading jdbc prepared-statement


【解决方案1】:

下面的描述可能会回答。

是的,通常批量插入比一次单个插入更快,因为它避免了每个插入语句都发生的中间通信。

但有时它会导致问题,因为插入/更新语句会在表/行上获得排他锁,这意味着当时没有其他进程/连接可以使用表。

如果您有多个同时使用 DB 的进程,其中一些正在从表中读取,一些正在写入,那么整个操作将在批量插入时被锁定/停止

所以批量插入将比单次插入锁定表更长的时间,如果锁定时间更长并且数据库未针对它进行调整,这可能会导致其他进程出现问题。

如果您只是在没有其他操作的情况下插入数据库,则从文件中进行批量插入(这要快得多),如果您有其他进程,请考虑锁定调整批量插入频率。

答案在这里:Performance Multiple inserts or multiple values single insert

【讨论】:

  • 这个答案我见过。它不讨论通过一个线程插入一行来比较多线程。
  • 是的,但是您提到“为每次插入创建线程”意味着多次单次插入。所以每个线程都会做单次插入,所以 DB 会被命中很多次。
  • 但这些不是“连续的”多次单次插入。因此,我们无法从您的回答中比较时间效率。
  • 可能你没有得到我的回答。看,虽然您的请求是异步进行的,但 SQL 插入将按顺序发生,这意味着有内部锁定机制将为每个插入锁定行/表,然后处理其他请求。你可以在这里得到更多的解释:dev.mysql.com/doc/refman/5.7/en/internal-locking.html
  • 我们可以使用行锁,由于多个插入在不同的行,线程可以并行执行。
【解决方案2】:

这是我向 SQL 数据库添加多个实例的方式: 用php2java.com把这段代码按照java转换一下,看看你需要什么。

global $db; //create database object
//if database tables does not exist already create them
        if($db->query('SELECT 1 from store_access') == FALSE) {
            $query = 'CREATE TABLE store_access (
                `access_id` bigint(20) NOT NULL AUTO_INCREMENT,
                `user_id` bigint(20) NOT NULL,
                `store_id` bigint(20) NOT NULL,
                `sales` bigint(20) NOT NULL,
                `purchase` bigint(20) NOT NULL,
                `vendors` bigint(20) NOT NULL,
                `clients` bigint(20) NOT NULL,
                `products` bigint(20) NOT NULL,
                `warehouse` bigint(20) NOT NULL,
                `returns` bigint(20) NOT NULL,
                `price_level` bigint(20) NOT NULL,
                `reports` bigint(20) NOT NULL,
                `expenses` bigint(20) NOT NULL,
                PRIMARY KEY (`access_id`)
            )'; 
            $result = $db->query($query) or die($db->error);
            echo 'Store Access Table created.<br>';
        } //creating user level table ends.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    相关资源
    最近更新 更多