当前位置: 首页 > 知识库问答 >
问题:

使用DB2的JDBC语句池没有显著的时间差

黄跃
2023-03-14

我使用的是JDBC db2驱动程序。JT400连接到Application System/400上的db2服务器,这是一个中档计算机系统。

我的目标是中插入来自IBM大型机外部的三个表,它们将是云实例(例如,Amazon WS)。

为了使演出更好

public class AS400JDBCManagedConnectionPoolDataSource extends AS400JDBCManagedDataSource implements ConnectionPoolDataSource, Referenceable, Serializable {
}

public class AS400JDBCManagedDataSource extends ToolboxWrapper implements DataSource, Referenceable, Serializable, Cloneable {
}
public class CustomerOrderEventHandler extends MultiEventHandler {

    private static Logger logger = LogManager.getLogger(CustomerOrderEventHandler.class);

    //private BasicDataSource establishedConnections = new BasicDataSource();

    //private DB2SimpleDataSource nativeEstablishedConnections = new DB2SimpleDataSource();

    private AS400JDBCManagedConnectionPoolDataSource dynamicEstablishedConnections =
            new AS400JDBCManagedConnectionPoolDataSource();

    private State3 orderState3;
    private State2 orderState2;
    private State1 orderState1;

    public CustomerOrderEventHandler() throws SQLException {
        dynamicEstablishedConnections.setServerName(State.server);
        dynamicEstablishedConnections.setDatabaseName(State.DATABASE);
        dynamicEstablishedConnections.setUser(State.user);
        dynamicEstablishedConnections.setPassword(State.password);
        dynamicEstablishedConnections.setSavePasswordWhenSerialized(true);
        dynamicEstablishedConnections.setPrompt(false);
        dynamicEstablishedConnections.setMinPoolSize(3);
        dynamicEstablishedConnections.setInitialPoolSize(5);
        dynamicEstablishedConnections.setMaxPoolSize(50);
        dynamicEstablishedConnections.setExtendedDynamic(true);
        Connection connection = dynamicEstablishedConnections.getConnection();
        connection.close();
    }

    public void onEvent(CustomerOrder orderEvent){
        long start =  System.currentTimeMillis();
        Connection dbConnection = null;
        try {
            dbConnection = dynamicEstablishedConnections.getConnection();
            long connectionSetupTime = System.currentTimeMillis() - start;

            state3 = new State3(dbConnection);
            state2 = new State2(dbConnection);
            state1 = new State1(dbConnection);

            long initialisation = System.currentTimeMillis() - start - connectionSetupTime;

            int[] state3Result = state3.apply(orderEvent);
            int[] state2Result = state2.apply(orderEvent);
            long state1Result = state1.apply(orderEvent);

            dbConnection.commit();

            logger.info("eventId="+ getEventId(orderEvent) +
                    ",connectionSetupTime=" + connectionSetupTime +
                    ",queryPreCompilation=" + initialisation +
                    ",insertionOnlyTimeTaken=" +
                    (System.currentTimeMillis() - (start + connectionSetupTime + initialisation)) +
                    ",insertionTotalTimeTaken=" + (System.currentTimeMillis() - start));
        } catch (SQLException e) {
            logger.error("Error updating the order states.", e);
            if(dbConnection != null) {
                try {
                    dbConnection.rollback();
                } catch (SQLException e1) {
                    logger.error("Error rolling back the state.", e1);
                }
            }
            throw new CustomerOrderEventHandlerRuntimeException("Error updating the customer order states.", e);
        }
    }

    private Long getEventId(CustomerOrder order) {
        return Long.valueOf(order.getMessageHeader().getCorrelationId());
    }
}
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

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

public class State2 extends State {

    private static Logger logger = LogManager.getLogger(DetailState.class);

    Connection connection;
    PreparedStatement preparedStatement;

    String detailsCompiledQuery = "INSERT INTO " + DATABASE + "." + getStateName() +
            "(" + DetailState.EVENT_ID + ", " +
            State2.ORDER_NUMBER + ", " +
            State2.SKU_ID + ", " +
            State2.SKU_ORDERED_QTY + ") VALUES(?, ?, ?, ?)";

    public State2(Connection connection) throws SQLException {
        this.connection = connection;
        this.preparedStatement = this.connection.prepareStatement(detailsCompiledQuery); // this is taking ~200ms each time
        this.preparedStatement.setPoolable(true); //might not be required, not sure
    }

    public int[] apply(CustomerOrder event) throws StateException {

        event.getMessageBody().getDetails().forEach(detail -> {
            try {
                preparedStatement.setLong(1, getEventId(event));
                preparedStatement.setString(2, getOrderNo(event));
                preparedStatement.setInt(3, detail.getSkuId());
                preparedStatement.setInt(4, detail.getQty());
                preparedStatement.addBatch();
            } catch (SQLException e) {
                logger.error(e);
                throw new StateException("Error setting up data", e);
            }
        });

        long startedTime = System.currentTimeMillis();
        int[] inserted = new int[0];
        try {
            inserted = preparedStatement.executeBatch();
        } catch (SQLException e) {
            throw new StateException("Error updating allocations data", e);
        }
        logger.info("eventId="+ getEventId(event) +
                ",state=details,insertionTimeTaken=" + (System.currentTimeMillis() - startedTime));
        return inserted;
    }

    @Override
    protected String getStateName() {
        return properties.getProperty("state.order.details.name");
    }
}

计时的度量如下所示,

对于第一个事件,为3个表创建PreparedStatement需要580ms

{"timeMillis":1489982655836,"thread":"ScalaTest-run-running-CustomerOrderEventHandlerSpecs","level":"INFO","loggerName":"com.xyz.customerorder.events.handler.CustomerOrderEventHandler",
"message":"eventId=1489982654314,connectionSetupTime=1,queryPreCompilation=580,insertionOnlyTimeTaken=938,insertionTotalTimeTaken=1519","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","threadId":1,"threadPriority":5}

对于第二个事件,需要470ms来准备3个表的语句,这比第一个事件少,但只有<100ms,我认为它要少得多,因为它甚至不应该进行编译。

{"timeMillis":1489982667243,"thread":"ScalaTest-run-running-PurchaseOrderEventHandlerSpecs","level":"INFO","loggerName":"com.xyz.customerorder.events.handler.CustomerOrderEventHandler",
"message":"eventId=1489982665456,connectionSetupTime=0,queryPreCompilation=417,insertionOnlyTimeTaken=1363,insertionTotalTimeTaken=1780","endOfBatch":false,"loggerFqcn":"org.apache.logging.log4j.spi.AbstractLogger","threadId":1,"threadPriority":5}

Q1)DB2 JDBC驱动程序在多个连接之间缓存语句吗?因为我在准备语句时没有看到太大的差异。(请参见示例,第一个使用~600ms,第二个使用~500ms)

ODP=开放数据路径

SQL包

用于JDBC和SQLJ语句缓存的IBM数据服务器驱动程序

共有1个答案

戈巴英
2023-03-14

关于语句缓存需要注意的几个重要事项:

  • 因为语句对象是给定连接的子对象,所以一旦连接关闭,所有子对象(例如所有语句对象)也必须关闭。
  • 不能将一个连接中的语句与另一个连接相关联。
  • 语句池可以由给定的JDBC驱动程序完成,也可以不完成。语句池也可以由连接管理层(即应用程序服务器)执行
  • 根据JDBC规范,statement.ispoolable()==falsepreparedstatement.ispoolable()==true的默认值,但是这个标志只是对JDBC驱动程序的提示。规范不能保证会发生语句池。

首先,我不确定JT400驱动程序是否进行语句缓存。您在问题评论中引用的文档“从Java和WebSphere优化对DB2 for i5/OS的访问”专门针对在WebSphere application server中使用JT400 JDBC驱动程序,在幻灯片#3中,它指出语句缓存来自WebSphere连接管理层,而不是本地JDBC驱动层。鉴于此,我将假设JT400 JDBC驱动程序本身不支持语句缓存。

<dataSource jndiName="jdbc/myDS" statementCacheSize="10">
    <jdbcDriver libraryRef="DB2iToolboxLib"/>
    <properties.db2.i.toolbox databaseName="YOURDB" serverName="localhost"/>
</dataSource>

<library id="DB2iToolboxLib">
    <fileset dir="/path/to/jdbc/driver/dir" includes="jt400.jar"/>
</library>
 类似资料:
  • 我试图在DB2 10.1 Windows上使用JDBC运行多语句查询,但由于语法错误而失败。以下是查询- 我知道这是由于数据库不理解查询结尾处的分号造成的。我如何设置查询分隔符为分号,这样就可以通过这个。

  • 我们使用spring数据中的Oracle AQ支持在同一数据源上同时使用JMS和JDBC,使用本地事务而不是XA。我们的设置基本上是参考手册中所描述的:在orcl上:aq jms连接工厂:使用本地数据源事务=“true”和本机jdbc提取器=“oracleNativeJdbcExtractor”HibernateTransactionManager(我现在正尝试对aq和Hibernate使用单一数

  • 最近我发现你可以用C#: 而不是即: 这可能是一个坏例子,可以用很多其他方式来解决。 是否存在“无语句范围”功能是一种良好实践的模式?

  • 我试图使用以下JDBC语句将一些值插入到来自Java的Oracle DB中: 序列创建如下: 我得到以下错误, 但当我尝试手动插入到表中时,它是成功的。 有什么问题?

  • 我正在尝试更新表,下面是我正在使用的查询 我还尝试了另一个查询: 测试了运行良好的select查询,不确定问题是什么,在IBMDB2中是否有所不同。

  • 我正在使用JDBC将数据从带分隔符的文件传输到db2数据库表。最初,我遇到了sqlcode=-104,sqlstate=42601,所以在进一步调试中,我发现了这个问题,它让我调用存储过程sysproc.admin_cmd。 我修改了调用并尝试运行过程版本,但仍然得到相同的错误: com.ibm.DB2.jcc.am.sqlsyntaxerrorexception:DB2 SQL错误:sqlcod