栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Java中MySQL插入语句的性能:批处理方式准备的语句与具有多个值的单个插入

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中MySQL插入语句的性能:批处理方式准备的语句与具有多个值的单个插入

JDBC只是数据库访问的Java SE标准,提供了标准接口,因此您实际上并不局限于特定的JDBC实现。MySQL Java连接器(Connector /
J)仅是MySQL数据库的JDBC接口的实现。根据经验,我参与了一个使用MySQL使用大量数据的项目,对于可生成的数据,我们最喜欢使用MyISAM:它可以实现更高的性能损失交易,但总的来说,MyISAM更快,但是InnoDB更可靠。

我也想知道大约一年前INSERT语句的性能,并且在我的代码架中找到了以下旧测试代码(对不起,它有点复杂,而且超出了您的问题范围)。以下代码包含4种插入测试数据的方式的示例:

  • INSERT
    s;
  • 分批
    INSERT
  • 手动散装
    INSERT
    (切勿使用-危险);
  • 最后 准备好批量
    INSERT
    )。

它使用TestNG作为运行程序,并使用一些自定义代码,例如:

  • runWithConnection()
    方法-确保在执行回调后连接被关闭或放回连接池(但低于用途声明关闭不可靠的战略的代码-即使没有
    try
    /
    finally
    减少代码);
  • IUnsafeIn<T, E extends Throwable>
    -一个自定义的回调接口,用于接受单个参数但可能会引发E类型异常的方法,例如:
    void handle(T argument) throws E;

    package test;

    import test.IUnsafeIn;

    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;

    import static java.lang.String.format;
    import static java.lang.String.valueOf;
    import static java.lang.System.currentTimeMillis;

    import core.SqlbaseTest;
    import org.testng.annotations.AfterSuite;
    import org.testng.annotations.BeforeSuite;
    import org.testng.annotations.BeforeTest;
    import org.testng.annotations.Test;

    public final class InsertVsBatchInsertTest extends SqlbaseTest {

    private static final int ITERATION_COUNT = 3000;private static final String CREATE_TABLE_QUERY = "CREATE TABLE IF NOT EXISTS ttt1 (c1 INTEGER, c2 FLOAT, c3 VARCHAr(5)) ENGINE = InnoDB";private static final String DROp_TABLE_QUERY = "DROP TABLE ttt1";private static final String CLEAR_TABLE_QUERY = "DELETE FROM ttt1";private static void withinTimer(String name, Runnable runnable) {    final long start = currentTimeMillis();    runnable.run();    logStdOutF("%20s: %d ms", name, currentTimeMillis() - start);}@BeforeSuitepublic void createTable() {    runWithConnection(new IUnsafeIn<Connection, SQLException>() {        @Override        public void handle(Connection connection) throws SQLException { final PreparedStatement statement = connection.prepareStatement(CREATE_TABLE_QUERY); statement.execute(); statement.close();        }    });}@AfterSuitepublic void dropTable() {    runWithConnection(new IUnsafeIn<Connection, SQLException>() {        @Override        public void handle(Connection connection) throws SQLException { final PreparedStatement statement = connection.prepareStatement(DROP_TABLE_QUERY); statement.execute(); statement.close();        }    });}@BeforeTestpublic void clearTestTable() {    runWithConnection(new IUnsafeIn<Connection, SQLException>() {        @Override        public void handle(Connection connection) throws SQLException { final PreparedStatement statement = connection.prepareStatement(CLEAR_TABLE_QUERY); statement.execute(); statement.close();        }    });}@Testpublic void run1SingleInserts() {    withinTimer("Single inserts", new Runnable() {        @Override        public void run() { runWithConnection(new IUnsafeIn<Connection, SQLException>() {     @Override     public void handle(Connection connection) throws SQLException {         for ( int i = 0; i < ITERATION_COUNT; i++ ) {  final PreparedStatement statement = connection.prepareStatement("INSERT INTO ttt1 (c1, c2, c3) VALUES (?, ?, ?)");  statement.setInt(1, i);  statement.setFloat(2, i);  statement.setString(3, valueOf(i));  statement.execute();  statement.close();         }     } });        }    });}@Testpublic void run2BatchInsert() {    withinTimer("Batch insert", new Runnable() {        @Override        public void run() { runWithConnection(new IUnsafeIn<Connection, SQLException>() {     @Override     public void handle(Connection connection) throws SQLException {         final PreparedStatement statement = connection.prepareStatement("INSERT INTO ttt1 (c1, c2, c3) VALUES (?, ?, ?)");         for ( int i = 0; i < ITERATION_COUNT; i++ ) {  statement.setInt(1, i);  statement.setFloat(2, i);  statement.setString(3, valueOf(i));  statement.addBatch();         }         statement.executeBatch();         statement.close();     } });        }    });}@Testpublic void run3DirtyBulkInsert() {    withinTimer("Dirty bulk insert", new Runnable() {        @Override        public void run() { runWithConnection(new IUnsafeIn<Connection, SQLException>() {     @Override     public void handle(Connection connection) throws SQLException {         final StringBuilder builder = new StringBuilder("INSERT INTO ttt1 (c1, c2, c3) VALUES ");         for ( int i = 0; i < ITERATION_COUNT; i++ ) {  if ( i != 0 ) {      builder.append(",");  }  builder.append(format("(%s, %s, '%s')", i, i, i));         }         final String query = builder.toString();         final PreparedStatement statement = connection.prepareStatement(query);         statement.execute();         statement.close();     } });        }    });}@Testpublic void run4SafeBulkInsert() {    withinTimer("Safe bulk insert", new Runnable() {        @Override        public void run() { runWithConnection(new IUnsafeIn<Connection, SQLException>() {     private String getInsertPlaceholders(int placeholderCount) {         final StringBuilder builder = new StringBuilder("(");         for ( int i = 0; i < placeholderCount; i++ ) {  if ( i != 0 ) {      builder.append(",");  }  builder.append("?");         }         return builder.append(")").toString();     }     @SuppressWarnings("AssignmentToForLoopParameter")     @Override     public void handle(Connection connection) throws SQLException {         final int columnCount = 3;         final StringBuilder builder = new StringBuilder("INSERT INTO ttt1 (c1, c2, c3) VALUES ");         final String placeholders = getInsertPlaceholders(columnCount);         for ( int i = 0; i < ITERATION_COUNT; i++ ) {  if ( i != 0 ) {      builder.append(",");  }  builder.append(placeholders);         }         final int maxParameterIndex = ITERATION_COUNT * columnCount;         final String query = builder.toString();         final PreparedStatement statement = connection.prepareStatement(query);         int valueIndex = 0;         for ( int parameterIndex = 1; parameterIndex <= maxParameterIndex; valueIndex++ ) {  statement.setObject(parameterIndex++, valueIndex);  statement.setObject(parameterIndex++, valueIndex);  statement.setObject(parameterIndex++, valueIndex);         }         statement.execute();         statement.close();     } });        }    });}

    }

看一下用@Test注释注释的方法:它们实际上执行

INSERT
语句。还请看一看
CREATE_TABLE_QUERY
常量:在源代码中,它使用InnoDB在装有MySQL
5.5(MySQL Connector / J 5.1.12)的计算机上产生以下结果:

InnoDBSingle inserts: 74148 msBatch insert: 84370 msDirty bulk insert: 178 msSafe bulk insert: 118 ms

如果将

CREATE_TABLE_QUERY
InnoDB 更改为MyISAM,则会看到显着的性能提升:

MyISAMSingle inserts: 604 msBatch insert: 447 msDirty bulk insert: 63 msSafe bulk insert: 26 ms

希望这可以帮助。

UPD:

对于第四种方法,您必须适当地自定义

max_allowed_packet
in
mysql.ini
(本
[mysqld]
节),使其足够大以支持真正的大数据包。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/421213.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号