Apache Tomcat JDBC Connection Pool плохая производительность при пакетной \ групповой вставке

Недавно я включил в свое приложение пул соединений JDBC Apache Tomcat (используя MySQL DB). Я пытался использовать Apache DBCP раньше, но мне не понравились его результаты, и реализация tomcat, казалось, соответствовала моим потребностям, даже несмотря на то, что я запускаю отдельное приложение Java и вообще не использую tomcat.

Недавно я столкнулся с огромной проблемой производительности при выполнении запросов пакетной (или групповой) вставки.

У меня есть поток, в котором я вставляю ~2500 записей в таблицу в пакетном режиме. При использовании пула соединений jdbc это занимает вечность по сравнению с несколькими секундами при возврате к открытию соединения для каждого запроса (без объединения в пул).

Я написал небольшое приложение, которое вставляет 30 строк в одну таблицу. Это занимает 12 секунд, когда пул, и ~ 800 миллисекунд, когда не пул.

До использования пула соединений я использовал com.mysql.jdbc.jdbc2.optional.MysqlDataSource как мой источник данных. Соединение было настроено с помощью следующей строки:

dataSource.setRewriteBatchedStatements(true);

Я совершенно уверен, что в этом основное различие между двумя подходами, но не смог найти эквивалентный параметр в jdbc-pool.

1 ответ

Решение

Драйвер MySql JDBC не поддерживает пакетные операции. RewriteBatchedStatement - лучшее, что вы можете получить. Вот код из mysql PreparedStatement.java:

 try {
            statementBegins();

            clearWarnings();

            if (!this.batchHasPlainStatements && this.connection.getRewriteBatchedStatements()) {

                if (canRewriteAsMultiValueInsertAtSqlLevel()) {
                    return executeBatchedInserts(batchTimeout);
                }

                if (this.connection.versionMeetsMinimum(4, 1, 0) && !this.batchHasPlainStatements && this.batchedArgs != null
                        && this.batchedArgs.size() > 3 /* cost of option setting rt-wise */) {
                    return executePreparedBatchAsMultiStatement(batchTimeout);
                }
            }

            return executeBatchSerially(batchTimeout);
        } finally {
            this.statementExecuting.set(false);

            clearBatch();
        }

Это одна из причин, почему я не люблю MySql и предпочитаю Postgres

РЕДАКТИРОВАТЬ:

Вы должны объединить пул соединений, пакетную операцию и опцию RewriteBatchedStatement. Вы можете установить опцию RewriteBatchedStatement через параметр URL-адреса jdbc: jdbc:mysql://localhost:3307/mydb?rewriteBatchedStatements=true

Другие вопросы по тегам