12

我需要设置一些特定的 Oracle JDBC 连接属性以加快 batch INSERTs ( defaultBatchValue) 和 mass SELECTs ( defaultRowPrefetch)。我收到了如何使用 DBCP 实现这一目标的建议(感谢 M. Deinum),但我想:

  • 保留默认的Tomcat jdbc连接池
  • 保留 application.yml 进行配置

我正在考虑spring.datasource.custom_connection_properties将来支持或类似的功能请求,因此试图假装这已经成为可能。我通过在创建 DataSource 时传递相关信息来做到这一点,并像这样操纵 DataSource 的创建:

@Bean
public DataSource dataSource() {
    DataSource ds = null;

    try {
        Field props = DataSourceBuilder.class.getDeclaredField("properties");
        props.setAccessible(true);
        DataSourceBuilder builder = DataSourceBuilder.create();
        Map<String, String> properties = (Map<String, String>) props.get(builder);

        properties.put("defaultRowPrefetch", "1000");
        properties.put("defaultBatchValue", "1000");

        ds = builder.url( "jdbc:oracle:thin:@xyz:1521:abc" ).username( "ihave" ).password( "wonttell" ).build();

        properties = (Map<String, String>) props.get(builder);

        log.debug("properties after: {}", properties);
    } ... leaving out the catches ...
    }
    log.debug("We are using this datasource: {}", ds);
    return ds;
}

在日志中,我可以看到我正在创建正确的数据源:

2016-01-18 14:40:32.924 DEBUG 31204 --- [           main] d.a.e.a.c.config.DatabaseConfiguration   : We are using this datasource: org.apache.tomcat.jdbc.pool.DataSource@19f040ba{ConnectionPool[defaultAutoCommit=null; ...

2016-01-18 14:40:32.919 DEBUG 31204 --- [           main] d.a.e.a.c.config.DatabaseConfiguration   : properties after: {password=wonttell, driverClassName=oracle.jdbc.OracleDriver, defaultRowPrefetch=1000, defaultBatchValue=1000, url=jdbc:oracle:thin:@xyz:1521:abc, username=ihave}

执行器显示我的代码替换了数据源:

在此处输入图像描述

但是设置没有激活,我可以在分析应用程序时看到。defaultRowPrefetch仍然会10导致 my s 比激活SELECT时慢得多。1000

4

4 回答 4

11

设置池连接属性应该可以工作。这些将被传递给 JDBC 驱动程序。将此添加到 application.properties:

spring.datasource.connectionProperties: defaultRowPrefetch=1000;defaultBatchValue=1000

编辑(一些背景信息):

另请注意,您可以通过 spring.datasource.* 配置任何 DataSource 实现特定的属性:有关更多详细信息,请参阅您正在使用的连接池实现的文档。

来源:spring-boot 文档

于 2016-01-18T19:13:56.470 回答
4

由于 Spring Boot 长期停产,我切换到 Spring Boot 2.1 及其新的默认连接池 Hikari。这里的解决方案更加简单,可以在 application.properties 或(如这里所示)application.yml 中完成:

spring:
  datasource:
    hikari:
      data-source-properties:
        defaultRowPrefetch: 1000

(在现实生活中的配置中会有其他几个配置项,但由于它们对所提出的问题不感兴趣,所以我在示例中将它们省略了)

于 2019-04-12T09:41:17.750 回答
3

一些额外的信息来补充@Cyril的答案。如果您想投票,请使用他的答案,而不是我的。

我有点困惑,设置最终在创建数据库连接时使用的附加连接属性是多么容易。所以我做了一点研究。

spring.datasource.connectionProperties参考文献没有提到。因此,我创建了一个问题。如果我使用了Spring Boot YML 编辑器,我会看到支持哪些属性。以下是STS在您创建and hit时的建议:application.ymlCtrl+Space

spring.datasource 的自动完成

由于松散的绑定,破折号无关紧要,但如果您按字面意思解释它,则属性名称是spring.datasource.connection-properties.

application.yml 中的正确设置如下所示:

spring:
    datasource:
        connection-properties: defaultBatchValue=1000;defaultRowPrefetch=1000
        ...

这很荣幸,我对质量SELECTs 的 perf4j 测量证明了这一点。

前:

2016-01-19 08:58:32.604 INFO 15108 --- [主] org.perf4j.TimingLogger:开始[1453190311227] 时间[1377] 标签[获取元素]

后:

2016-01-19 08:09:18.214 INFO 9152 --- [main] org.perf4j.TimingLogger: start[1453187358066] time[147] tag[get elements]

完成 SQL 语句所需的时间从 1377ms 下降到 147ms,这在性能上是一个巨大的进步。

于 2016-01-19T08:13:44.837 回答
1

在对 Tomcat 代码进行了一番挖掘之后,我发现dataSource.getPoolProperties().getDbProperties()Properties实际用于为池生成连接的对象。

如果您使用BeanPostProcessor@m-deinum 提到的方法,而是使用它来填充dbProperties类似的方法,您应该能够以一种使它们粘住并传递给 Oracle 驱动程序的方式添加属性。

import java.util.Properties;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolConfiguration;

@Component
public class OracleConfigurer implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof DataSource) {
            DataSource dataSource = (DataSource)bean;
            PoolConfiguration configuration = dataSource.getPoolProperties();
            Properties properties = configuration.getDbProperties();
            if (null == properties) properties = new Properties();
            properties.put("defaultRowPrefetch", 1000);
            properties.put("defaultBatchValue", 1000);
            configuration.setDbProperties(properties);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        return bean;
    }
}
于 2016-09-13T23:29:54.793 回答