druid 首次请求创建 statement 很慢

sirbozc5  于 4个月前  发布在  Druid
关注(0)|答案(1)|浏览(77)

使用 druid 连接池,前几次请求总是特别慢,经过 debug 分析:druid 在应用启动时建立的连接,在首次执行请求时,都会进行创建 statement 操作,而这一步耗时特别长。后面再执行请求时,就没有创建 statement 的操作,请求处理的也特别快。

请大佬帮忙分析一下,这个第一次请求耗时是否可以优化?现在应用启动后,前几次请求都特别长,体验非常不好。

应用启动时,druid 创建了连接,这一步符合预期:

2021-07-23 15:32:11.599  WARN 26288 --- [      main] com.alibaba.druid.pool.DruidDataSource  [1243] : removeAbandoned is true, not use in production.
2021-07-23 15:32:11.856 DEBUG 26288 --- [      main] druid.sql.Connection                    [129] : {conn-10001,procId-55682} connected
2021-07-23 15:32:11.957 DEBUG 26288 --- [      main] druid.sql.Connection                    [129] : {conn-10002,procId-55684} connected
2021-07-23 15:32:12.062 DEBUG 26288 --- [      main] druid.sql.Connection                    [129] : {conn-10003,procId-55685} connected

首次请求时,创建 statment 用了将近 200ms,见下面 {conn-10030, pstmt-20000} created 日志,导致首次请求特别慢。

2021-07-23 15:32:28.498 DEBUG 26288 --- [l-thread-1] druid.sql.Connection                    [129] : {conn-10030} pool-connect
2021-07-23 15:32:28.501 DEBUG 26288 --- [l-thread-1] druid.sql.Connection                    [129] : {conn-10030} setAutoCommit false
2021-07-23 15:32:28.670 DEBUG 26288 --- [l-thread-1] druid.sql.Statement                     [134] : {conn-10030, pstmt-20000} created. insert into table_name

2021-07-23 15:32:28.687 DEBUG 26288 --- [l-thread-1] druid.sql.Statement                     [134] : {conn-10030, pstmt-20000} Parameters : [..]
2021-07-23 15:32:28.687 DEBUG 26288 --- [l-thread-1] druid.sql.Statement                     [134] : {conn-10030, pstmt-20000} Types : [VARCHAR, INTEGER]
2021-07-23 15:32:28.700 DEBUG 26288 --- [l-thread-1] druid.sql.Statement                     [134] : {conn-10030, pstmt-20000} executed. 14.004616 millis. insert into table_name

druid 版本:

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>

druid 配置:

spring:
  datasource:
    dynamic:
      primary: master                                                                               
      strict: false                                                                                 
      datasource:
        master:                                                                                                                                                             
          url: jdbc:mysql://ip:port/database?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useAffectedRows=true&nullCatalogMeansCurrent=true
          username: xxx
          password: xxx                                                                              
          driver-class-name: com.mysql.jdbc.Driver                                                                               
          druid:                                                                                
            default-auto-commit: true                                                                               
            initial-size: 30                                                                                
            min-idle: 30                                                                                
            max-active: 30                                                                              
            test-while-idle: true   
            keep-alive: true                                                                        
            time-between-eviction-runs-millis: 60000
            min-evictable-idle-time-millis: 300000
            max-evictable-idle-time-millis: 900000                                                                         
            connection-init-sqls: SELECT now()                                                                           
            validation-query: SELECT now()                                                                               
            connection-error-retry-attempts: 3                                                                              
            remove-abandoned: true                                                                              
            transaction-query-timeout: 200                                                                 
            max-wait: 100                                                                                                                                                       
            filters: slf4j,wall,stat
            filter:
              slf4j:
                enabled: true
                statement-log-enabled: true
              stat:
                enabled: true
            web-stat-filter:
              enabled: true
              url-pattern: "/*"
              exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
            stat-view-servlet:
              url-pattern: "/druid/*"
              reset-enable: false
              login-username: admin
              login-password: admin
              enabled: true
        slave:
          (配置略)

mysql 版本: MySQL 5.7.15

92dk7w1h

92dk7w1h1#

我也遇到类似问题, 在springboot项目中使用mybatis+druid, 项目启动后第一次访问慢, 体现在18,19行耗时有450ms左右, 已打开debug日志,第一次之后请求访问就比较快了,只有30ms左右。

版本:springboot 2.4.1,mybatis-spring-boot-starter 2.1.4, druid 1.2.6,druid-spring-boot-starter 1.2.6

配置如下:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&autoReconnect=true&useSSL=false&verifyServerCertificate=false
username: root
password: 123

使用druid数据源

type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
druid:

配置初始化大小、最小、最大

initial-size: 10
minIdle: 10
max-active: 20

配置获取连接等待超时的时间(单位:毫秒)

max-wait: 60000

配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

time-between-eviction-runs-millis: 2000

配置一个连接在池中最小生存的时间,单位是毫秒

min-evictable-idle-time-millis: 600000
max-evictable-idle-time-millis: 900000

用来测试连接是否可用的SQL语句,默认值每种数据库都不相同,这是mysql

validationQuery: select 1

应用向连接池申请连接,并且testOnBorrow为false时,连接池将会判断连接是否处于空闲状态,如果是,则验证这条连接是否可用

testWhileIdle: true

如果为true,默认是false,应用向连接池申请连接时,连接池会判断这条连接是否是可用的

testOnBorrow: false

如果为true(默认false),当应用使用完连接,连接池回收连接的时候会判断该连接是否还可用

testOnReturn: false

是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle

poolPreparedStatements: true

要启用PSCache,必须配置大于0,当大于0时, poolPreparedStatements自动触发修改为true,

在Druid中,不会存在Oracle下PSCache占用内存过多的问题,

可以把这个数值配置大一些,比如说100

maxOpenPreparedStatements: 20

连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作

keepAlive: true

Spring 监控,利用aop 对指定接口的执行时间,jdbc数进行记录

aop-patterns: "com.123.boot.mapper.*"
########### 启用内置过滤器(第一个 stat必须,否则监控不到SQL)##########
filters: stat,wall,log4j2

自己配置监控统计拦截的filter

filter:

开启druiddatasource的状态监控

stat:
enabled: true
db-type: mysql

开启慢sql监控,超过2s 就认为是慢sql,记录到日志中

log-slow-sql: true
slow-sql-millis: 2000

日志监控,使用slf4j 进行日志输出

slf4j:
enabled: true
statement-log-error-enabled: true
statement-create-after-log-enabled: false
statement-close-after-log-enabled: false
result-set-open-after-log-enabled: false
result-set-close-after-log-enabled: false
########## 配置WebStatFilter,用于采集web关联监控的数据 ##########
web-stat-filter:
enabled: true # 启动 StatFilter
url-pattern: /* # 过滤所有url
exclusions: ".js,.gif,.jpg,.png,.css,.ico,/druid/" # 排除一些不必要的url
session-stat-enable: true # 开启session统计功能
session-stat-max-count: 1000 # session的最大个数,默认100
########## 配置StatViewServlet(监控页面),用于展示Druid的统计信息 ##########
stat-view-servlet:
enabled: true # 启用StatViewServlet
url-pattern: /druid/
# 访问内置监控页面的路径,内置监控页面的首页是/druid/index.html
reset-enable: false # 不允许清空统计数据,重新计算
login-username: root # 配置监控页面访问密码
login-password: 123
allow: 127.0.0.1 # 允许访问的地址,如果allow没有配置或者为空,则允许所有访问
deny:

相关问题