性能优化常用策略 #
简介 #
DBPlusEngine 本身在代码、参数等方面已对通用场景的性能进行过大量优化,默认参数的情况下启动 DBPlusEngine 即可达到较优性能。对性能要求更高的用户,可以针对场景、环境进行进一步的优化。
Java 相关优化 #
Java 版本 #
目前 DBPlusEngine 最低支持 Java 8。截至本文编写,最新的 LTS(Long term support,长期支持版本) 为 Java 17。
新版本的 Java 相比旧版本 Java 在 JDK 类库、JIT、GC 等方面会有一定的性能提升。
JVM 参数 #
设置合适的 -Xmx #
JVM 堆内存参数需要结合业务与环境设置,不能太小也不宜过大。堆内存太小可能会导致 GC 次数增加,堆内存过大可能会增加 GC 停顿时长,具体表现为某些 SQL 的执行延时增加。
对于 OLTP 场景,在所有 SQL 都能够下推到数据库执行的情况下,堆内存一般不超过 16 GB。
对于使用联邦查询的场景,由于部分计算需要在 DBPlusEngine 进程的内存中进行,堆内存可以根据实际数据量适当增加,避免发生 OOM。
-Xss 设置 #
-Xss 在一般场景下无须专门设置。以下情况可能需要考虑调整:
- 使用 jOOQ
在 jOOQ 类加载过程中,类加载相关调用栈会比较深,-Xss 过小(例如少于 512k)可能会发生 java.lang.StackOverflowError,一般 -Xss 不小于 1m 即可。
- SQL 特别长或参数特别多
当 SQL 较长或参数非常多时,SQL 解析可能会存在较深的调用栈。例如以下 SQL:
insert into some_table values (1,'foo'), (2,'bar'), ..., (100000,'baz')
在 values 数量非常多的情况下,SQL 解析所需的调用栈会比较深,此时如果 -Xss 过小就可能会发生java.lang.StackOverflowError。
-XX:+AggressiveHeap #
适用于:Java 10 及更高版本
启用该选项,JVM 会为长时间运行的内存密集型应用程序优化堆,在高并发场景对 DBPlusEngine 性能提升有帮助。
NUMA 环境相关参数 #
-XX:+UseNUMA #
在 NUMA 环境下,使用该参数可以优化 JVM 的内存分配。由于 JVM 会启动时会检测当前是否 NUMA 环境,即使在非 NUMA 环境下启动了该参数,也不会产生任何影响。
JIT 相关参数 #
-XX:+SegmentedCodeCache #
适用于:Java 9 及更高版本
该参数会启用分段代码缓存,对 DBPlusEngine 性能提升有帮助。
-XX:+UseJVMCICompiler #
适用于:OpenJDK 11
使用 JVMCI 作为默认编译器。启用该选项对 DBPlusEngine 性能峰值有提升效果。
使用该参数要求先启用以下参数:
-XX:+UnlockExperimentalVMOptions
DBPlusEngine 优化 #
DBPlusEngine 参数优化 #
max-connections-size-per-query #
默认值:1
该参数控制每次执行查询时,在每个数据源上允许获取的最大连接数量。当存在路由到多库/多表的查询请求时,适当增加该参数可以提高查询的并发执行度。
proxy-backend-query-fetch-size #
适用于:Proxy
默认值:-1。
该参数控制 Proxy 向存储节点查询数据时,每次网络交互所传输的数据行数。
使用默认值 -1 的情况下,Proxy 向 MySQL 存储节点查询数据时会尽量使用流式查询,能够减少 Proxy 内存使用,避免在结果集非常大的情况下发生 OOM。
如果结果集行数可控,可以适当增加该参数,可能会减少 Proxy 与数据库的交互次数以减少 SQL 执行延时,但会增加 Proxy 的内存使用。
proxy-frontend-executor-size #
适用于:Proxy
该参数控制 Proxy 中 Netty 的线程数量,默认值为 Proxy 所在 JVM 进程可用的逻辑 CPU 数量 * 2。
在 Proxy 承受一定负载的情况下,通过 top -H
可以查看 JVM 中线程的资源使用情况。其中,命名以 epollEventLoopGroup
为前缀的线程是 Netty 线程。
在 Proxy 吞吐量达到瓶颈的情况下:如果 Netty 线程的平均 CPU 使用率较低,可以适当减少线程数量,以减少线程切换等存在性能开销的情况;反之,则需要适当增加线程数量,以增加网络 I/O 处理能力。
DBPlusEngine 第三方依赖参数优化 #
关闭 Netty 泄漏检测 #
适用于:Proxy
Netty 具备泄漏检测能力,存在 4 种检测等级:
- DISABLED:关闭。
- SIMPLE:(默认)简单采样,对性能开销较小。
- ADVANCED:在简单采样的基础上,同时记录泄漏资源的近期访问代码路径,开销会相对较大。
- PARANOID:(仅适用于测试)检测所有资源是否存在泄漏,性能开销非常大。
Netty 泄漏检测默认是 SIMPLE 级别,性能开销较低。
但对于稳定版本的 Proxy,可以完全关闭泄漏检测以消除泄漏检测逻辑自身的性能开销。
-Dio.netty.leakDetection.level=DISABLED
DBPlusEngine Proxy 客户端优化 #
MySQL Connector/J 参数建议 #
启用 Server 端 Prepared Statement #
参数名 | MySQL Connector/J 默认值 | 连接 DBPlusEngine Proxy 建议值 | 描述 |
---|---|---|---|
cachePrepStmts | true | true | 在驱动内部缓存 Prepared Statement。 |
useServerPrepStmts | false | true | 使用服务端 Prepared Statement。 |
prepStmtCacheSize | 25 | 8192 | 驱动内部每个数据库连接的 Prepared Statement 缓存大小。 |
prepStmtCacheSqlLimit | 256 | 2048 | 允许缓存的 SQL 语句长度限制。 |
在 DBPlusEngine Proxy 内部会对 Server 端 Prepared Statement 的语句进行 SQL 解析、SQL 上下文进行缓存,能够减少 SQL 执行的开销与延时。
TCP 缓冲区配置 #
默认情况下,MySQL Connector/J 的 TCP 缓冲区会使用操作系统的默认值。如果需要调整为特定的值,可以通过以下两个参数配置。
- tcpRcvBuf
- tcpSndBuf
合并批量操作 #
当使用 PreparedStatement 的 addBatch/executeBatch 等方法时,由于 MySQL 协议本身的局限性,批量操作无法直接通过 MySQL 协议实现。可以通过以下参数启用 MySQL Connector/J 的批量操作改写:
- rewriteBatchedStatements=true
- allowMultiQueries=false(MySQL Connector/J 默认值)
当开启批量操作改写后:
- insert SQL 会自动被改写成多组 values 的形式;
- update/delete 语句会自动改写成多语句的形式。
DBPlusEngine Proxy 内部会自动识别 MySQL COM_SET_OPTIONS
指令,因此使用批量操作的同时需要保持 allowMultiQueries=false 参数设置。
避免长时间网络等待 #
可以通过设置 socketTimeout 减少异常连接的等待时间,建议最小设置为 SQL 最大执行时间加上一个 RTT (Round-Trip Time),实际业务场景考虑网络波动和数据库高峰压力需要设的大一些。
PostgreSQL/openGauss JDBC Driver 参数建议 #
TCP 缓冲区配置 #
默认情况下,PostgreSQL/openGauss JDBC Driver 的 TCP 缓冲区会使用操作系统的默认值。如果需要调整为特定的值,可以通过以下两个参数配置。
- receiveBufferSize
- sendBufferSize
环境优化 #
CPU 亲和性 #
在一些用户环境下,机器上某些 CPU 核心可能有专门用途。
例如在某 128 核的环境下,CPU 0-15 核被专门用于处理网络中断,此时如果 DBPlusEngine 在所有 CPU 上运行,网络处理能力、DBPlusEngine 最大吞吐量可能会受到影响。
此时可以为 DBPlusEngine 所在 JVM 执行可用的 CPU。例如,使用 numactl
,指定 CPU 16-127 核可用于 DBPlusEngine,则将启动命令修改为:
numactl -C 16-127 java ...# 省略其他参数
排除网卡性能瓶颈 #
DBPlusEngine 属于网络 I/O 密集的应用,尤其是 Proxy,会同时与数据库客户端、存储节点交互,网络收发频繁。此时需要避免网络中断的处理成为 DBPlusEngine 的性能瓶颈,尤其在网卡队列较少的情况下,网卡中断处理达到瓶颈会限制 DBPlusEngine 的最大吞吐量。
如果网卡只有单队列,网络中断处理达到上限(通常表现是某个 CPU 核心的 hi/si 使用率接近 100%,其他 CPU 核心使用率相对较低),可以考虑通过启用 irqbalance 等方式在多个 CPU 核心分摊网络中断处理。
场景建议 #
为分片键配置索引 #
在数据分片场景下,分片键如果不是主键,建议增加索引,以减少通过分片键为条件的 SQL 执行延时。
分页修正与分页查询优化 #
对于能够路由到单库/单表的分页查询 SQL,DBPlusEngine 会直接将 SQL 下推到存储节点执行。
当分页查询的 SQL 路由到多个库或者多个表时,为确保查询的正确性,DBPlusEngine 会对语句的分页参数进行改写。尤其在大偏移量查询的情况下,经过分页修正的 SQL 查询效率会明显降低。对于可能涉及大偏移量查询的情况,建议不使用 LIMIT 方式进行分页。可以考虑构建行记录数量与行偏移量的二级索引、使用上次分页数据结尾 ID 作为下次查询条件的等分页方式,避免 SQL 执行延时过高。
避免在 SQL 中包含不需要的数据 #
用户在编写 SQL 时,建议精准控制所需的列、查询条件,可以有效减少 SQL 执行开销、网络 I/O 开销。与传统直接连接数据库情况相比,DBPlusEngine Proxy 的网络拓扑更为复杂,传输不必要的数据所带来的网络 I/O 开销会更明显。