Apache ShardingSphere 5.1.0 执行引擎性能优化揭秘

c8bc782f32ca269d0b2081364157d32c.png

端正强

SphereEx 高级中间件开发工程师,Apache ShardingSphere Committer。

2018 年开始接触 Apache ShardingSphere 中间件,曾主导公司内部海量数据的分库分表,有着丰富的实践经验;热爱开源,乐于分享,目前专注于 Apache ShardingSphere 内核模块开发。

前言

在 Apache ShardingSphere 5.1.0 前几篇技术解读文章中,我们了解了解析引擎提供的 SQL 格式化功能,以及最新优化的高可用功能。除了不断为用户提供实用的新特性外,Apache ShardingSphere 社区一直在努力提升性能。

以单库 10 分片的 t_order 表为例,max-connections-size-per-query 使用默认配置 1,如果用户执行 SELECT * FROM t_order 语句则会导致全路由。由于每个查询只允许在同一个数据库上创建一个数据库连接,因此底层真实执行的 SQL 结果会被提前加载至内存进行处理,该场景限制了数据库连接资源的消耗,但是会占用更多的内存资源。如果用户将 max-connections-size-per-query 调整为 10,则可以在执行真实 SQL 时,同时创建 10 个数据库连接,由于数据库连接能够持有结果集,因此该场景不会额外占用内存资源,但是很显然会消耗更多的数据库连接资源。

为了更好地解决数据库连接资源和内存资源占用的问题,在刚刚发布的 5.1.0 版本中,我们对 SQL 执行引擎的性能进行了优化,通过 SQL 改写引擎进行优化性改写,将同一个数据源上的多条真实 SQL,使用 UNION ALL 语句进行合并,从而有效降低了执行引擎对数据库连接资源的消耗,同时减少了内存归并的发生,大幅度提升了 OLTP 场景下 SQL 查询性能。下面我们将结合具体的 SQL 实例,为大家详细解读执行引擎性能优化的细节。

执行引擎原理

在解读执行引擎性能优化之前,让我们先来回顾下 Apache ShardingSphere 微内核及内核流程中执行引擎的原理。如下图所示,Apache ShardingSphere 微内核包含了 SQL 解析、SQL 路由、SQL 改写、SQL 执行和结果归并等核心流程。

8639a0be7b14fb3c77c5a7790ba5146c.png

SQL 解析引擎负责对用户输入的 SQL 语句进行解析,并生成包含上下文信息的 SQLStatement。SQL 路由引擎则根据解析上下文提取出分片条件,再结合用户配置的分片规则,计算出真实 SQL 需要执行的数据源并生成路由结果。SQL 改写引擎根据 SQL 路由引擎返回的结果,对原始 SQL 进行改写,具体包括了正确性改写和优化性改写。SQL 执行引擎则负责将 SQL 路由和改写引擎返回的真实 SQL 安全且高效地发送到底层数据源执行,执行的结果集最终会由归并引擎进行处理,生成统一的结果集返回给用户。

从整个微内核的执行流程可以看出,SQL 执行引擎直接与底层数据库交互,并负责持有执行的结果集,可以说执行引擎的性能和资源消耗,直接关系到整个 Apache ShardingSphere 的性能和资源消耗,因此 Apache ShardingSphere 内部采用了一套自动化的 SQL 执行引擎,负责在执行性能和资源消耗间进行权衡。

从执行性能的角度来看,为每个分片的执行语句分配一个独立的数据库连接,可以充分利用多线程来提升执行性能,也可以将 I/O 所产生的消耗并行处理。此外,为每个分片分配一个独立的数据库连接,还能够避免过早的将查询结果集加载至内存,独立的数据库连接,能够持有查询结果集游标位置的引用,在需要获取相应数据时移动游标即可。

从资源控制的角度来看,应当对业务访问数据库的连接数量进行限制,避免某一业务占用过多的数据库连接资源,影响其他业务的正常访问。特别是在一个数据库实例中存在较多分表的情况下,一条不包含分片键的逻辑 SQL 将产生落在同库不同表的大量真实 SQL,如果每条真实 SQL 都占用一个独立的连接,那么一次查询无疑将会占用过多的资源。

为了解决执行性能和资源控制的冲突问题,Apache ShardingSphere 提出了连接模式的概念,下面是 Apache ShardingSphere 源码对于连接模式的定义。

 
 
/**
 * Connection Mode.
 */
public enum ConnectionMode {

    MEMORY_STRICTLY, CONNECTION_STRICTLY
}

从 ConnectionMode 枚举类中成员的命名可以看出,SQL 执行引擎将数据库连接划分为 MEMORY_STRICTLY 和 CONNECTION_STRICTLY

  • MEMORY_STRICTLY 代表内存限制模式,当采用内存限制模式时,对于同一个数据源,如果逻辑表对应了 10 个真实表,那么 SQL 执行引擎会创建 10 个连接并行地执行,由于每个分片的结果集都有对应的连接进行持有,因此无需将结果集提前加载到内存中,从而有效地降低了内存占用;

  • CONNECTION_STRICTLY 代表连接限制模式,当采用连接限制模式时,SQL 执行引擎只会在同一个数据源上创建一个连接,严格控制对数据库连接资源的消耗,在真实 SQL 执行之后立即将结果集加载至内存,因此会占用部分内存空间。

那么,Apache ShardingSphere SQL 执行引擎是如何帮助用户选择连接模式的呢?SQL 执行引擎选择连接模式的逻辑可以参考下图:

81fe9426fe8269cba84f5a8b55e94f46.png

用户通过配置 maxConnectionSizePerQuery 参数,可以指定每条语句在同一个数据源上最大允许的连接数。通过上面的计算公式,当每个数据库连接需执行的 SQL 数量小于等于 1 时,说明当前可以满足每条真实执行的 SQL 都分配一个独立的数据库连接,此时会选择内存限制模式,同一个数据源允许创建多个数据库连接进行并行执行。反之则会选择连接限制模式,同一个数据源只允许创建一个数据库连接进行执行,然后将结果集加载进内存结果集,再提供给归并引擎使用。

执行引擎优化

在熟悉了 Apache ShardingSphere SQL 执行引擎的内部原理之后,我们发现使用内存限制模式时,会消耗更多的数据库连接,但是能够通过并发执行获得更好的性能,使用连接限制模式能够有效控制连接资源的使用,但是会占用过多的内存,执行的性能也会受到影响。

那么,有没有可能使用尽可能少的数据库连接,同时占用较少内存的执行方式呢?根据前文对 SQL 执行引擎的分析,执行模式的选择主要是根据同一个数据源上路由结果的数量,因此最直接的优化思路,就是对同一个数据源上的路由结果进行合并。SQL 语句天然支持通过 UNION ALL 对多条查询语句进行合并,因此我们采用 UNION ALL 方案,对同一个数据源中的多条真实 SQL 进行优化性改写,从而将多条真实 SQL 改写为一条 S

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值