Mybatis 有哪些不同的 Executor 实现? 它们有什么区别?

MyBatis 提供了几种不同的 Executor 接口的实现类,这些实现类被称为 执行器类型 (ExecutorType)。 不同的 Executor 实现类采用了不同的 SQL 执行策略,从而在性能、功能和适用场景上有所区别。 MyBatis 默认提供了以下三种主要的 Executor 实现:

  1. SimpleExecutor (简单执行器)
  2. ReuseExecutor (复用执行器)
  3. BatchExecutor (批量执行器)

除了这三种主要的执行器,MyBatis 还有一个 CachingExecutor (缓存执行器),但 CachingExecutor 并不是一个独立的执行器类型,而是一个 装饰器 (Decorator),它 装饰在其他执行器之上,为其添加二级缓存的支持

以下是各种 Executor 实现的详细区别:

1. SimpleExecutor (简单执行器)

  • 描述: SimpleExecutor 是 MyBatis 默认的执行器类型。 它也是 最简单 的执行器实现。
  • 核心特点:
    • 每次执行 SQL 语句,都会创建一个新的 Statement 对象。 无论执行多少次相同的 SQL 语句 (即使只是参数不同),SimpleExecutor 都会重新创建 Statement 对象。
    • 不复用 Statement 对象。
    • 不支持批量 SQL 执行。
  • 性能特点:
    • 性能相对较低。 由于每次执行 SQL 都需要创建新的 Statement 对象,会增加对象创建和销毁的开销,以及 Statement 预编译的开销 (虽然 JDBC 驱动通常会缓存预编译语句,但仍然有开销)。
    • 资源消耗相对较高。 频繁创建 Statement 对象会增加资源消耗。
  • 适用场景:
    • 简单查询、少量 SQL 操作。
    • 对性能要求不高,或者 SQL 执行次数不多的场景。
    • 易于理解和调试。 由于每次执行都是独立的,执行流程比较清晰。
  • Statement 处理: 每次执行 SQL 都创建新的 Statement,执行完成后立即关闭 Statement
  • 批量支持: 不支持批量 SQL 执行。
  • 一级缓存: 支持一级缓存。 在同一个 SqlSession 中,如果执行相同的查询,会从一级缓存中获取结果 (默认行为)。

2. ReuseExecutor (复用执行器)

  • 描述: ReuseExecutor 的目标是 复用 Statement 对象,以提高性能。
  • 核心特点:
    • 对于相同的 SQL 语句 (SQL 文本完全一致,只是参数不同),会复用之前创建的 Statement 对象。
    • 如果执行的 SQL 语句与之前执行过的 SQL 语句完全相同 (SQL 文本相同),ReuseExecutor 会尝试复用之前创建的 Statement 对象,并重新设置参数,然后执行。
    • 复用的关键是 SQL 语句文本的完全一致。 如果 SQL 文本稍有不同 (例如空格、注释等差异),则不会被视为相同的 SQL 语句,不会复用 Statement
    • 不支持批量 SQL 执行。
  • 性能特点:
    • 性能比 SimpleExecutor 高。 复用 Statement 对象可以减少 Statement 对象的创建和预编译开销,尤其是在需要重复执行相同 SQL 语句的场景下,性能提升更明显。
    • 资源消耗相对较低。 复用 Statement 对象可以减少资源消耗。
  • 适用场景:
    • 需要重复执行相同 SQL 语句的场景。 例如循环查询、分页查询等。
    • 对性能有一定要求,但不需要批量操作的场景。
  • Statement 处理: 对于相同的 SQL 语句,复用 Statement 对象,执行完成后将 Statement 对象缓存起来,以便下次复用。 对于不同的 SQL 语句,仍然会创建新的 Statement 对象。
  • 批量支持: 不支持批量 SQL 执行。
  • 一级缓存: 支持一级缓存,行为与 SimpleExecutor 相同。

3. BatchExecutor (批量执行器)

  • 描述: BatchExecutor 专为 批量 SQL 操作 设计,旨在提高批量操作的性能。
  • 核心特点:
    • 支持批量 SQL 执行。 可以将多条 SQL 语句 (例如多个 INSERT, UPDATE, DELETE 语句) 收集起来,一次性发送到数据库执行。
    • 复用 Statement 对象进行批量操作。 对于批量操作,BatchExecutor 会复用同一个 Statement 对象,并将多条 SQL 语句添加到批处理中,然后一次性执行。
    • 需要数据库驱动和 SQL 语句支持批量执行。 并非所有数据库和 SQL 语句都支持批量执行。 通常 INSERT, UPDATE, DELETE 语句支持批量执行,而 SELECT 语句不支持批量执行 (批量查询通常使用 IN 条件或 UNION ALL 等方式实现)。
  • 性能特点:
    • 性能最高 (针对批量操作)。 批量执行 SQL 语句可以显著减少客户端和数据库之间的网络交互次数,大幅提升批量操作的效率。
    • 资源消耗相对较高 (可能)。 批量操作可能会在客户端和数据库端占用较多内存,需要根据实际情况进行评估。
  • 适用场景:
    • 批量插入、批量更新、批量删除等批量操作场景。
    • 需要处理大量数据,并且性能要求很高的场景。
  • Statement 处理: 对于批量操作,复用同一个 Statement 对象,并将多条 SQL 语句添加到批处理中,一次性执行。 对于非批量操作,行为类似于 SimpleExecutor (每次执行创建新的 Statement)。
  • 批量支持: 完全支持批量 SQL 执行 (针对支持批量操作的 SQL 语句)。
  • 一级缓存: 支持一级缓存。 但一级缓存的行为在 BatchExecutor 中有所不同。 由于批量操作通常是多条不同的 SQL 语句 (只是 SQL 类型相同),一级缓存的命中率可能较低。 BatchExecutor 默认会禁用一级缓存的自动刷新 (flushCacheRequired = false),以提高批量操作的性能。 开发者需要手动管理一级缓存的刷新。

4. CachingExecutor (缓存执行器)

  • 描述: CachingExecutor 不是一种独立的执行器类型,而是一个装饰器 (Decorator)。 它 装饰在其他执行器 (例如 SimpleExecutor, ReuseExecutor, BatchExecutor) 之上,为其添加二级缓存的支持。
  • 核心特点:
    • 二级缓存的入口和管理者。 所有对二级缓存的操作 (例如缓存的读取、写入、失效) 都通过 CachingExecutor 进行。
    • 本身不负责 SQL 执行。 CachingExecutor 只是一个装饰器,它会将 SQL 执行请求 委托给被装饰的执行器 (例如 SimpleExecutor, ReuseExecutor, BatchExecutor) 来完成实际的 SQL 执行。
    • 在执行 SQL 前,先检查二级缓存。 如果二级缓存命中,则直接返回缓存结果。 如果二级缓存未命中,则委托给被装饰的执行器执行 SQL,并将查询结果添加到二级缓存中。
    • 负责维护二级缓存的生命周期和一致性。 例如在执行更新、插入、删除操作后,会失效相关的二级缓存。
  • 性能特点:
    • 可以显著提高查询性能 (如果二级缓存命中率高)。 二级缓存可以减少数据库访问次数,提高系统吞吐量。
    • 增加了一定的缓存管理开销。 需要维护缓存数据的存储、读取和失效,会增加一定的内存和 CPU 开销。
  • 适用场景:
    • 需要使用二级缓存来提高查询性能的场景。
    • 读多写少,缓存命中率较高的场景。
    • 对数据一致性要求不是非常严格,可以容忍短暂缓存不一致的场景 (取决于缓存配置和失效策略)。
  • Statement 处理: CachingExecutor 本身不处理 StatementStatement 的处理仍然由被装饰的执行器负责 (例如 SimpleExecutor, ReuseExecutor, BatchExecutor)。
  • 批量支持: CachingExecutor 的批量支持取决于被装饰的执行器。 如果装饰的是 BatchExecutor,则支持批量操作。
  • 一级缓存: CachingExecutor 本身 不直接管理一级缓存,一级缓存的管理仍然由被装饰的执行器负责。 但 CachingExecutor在一级缓存的基础上,添加二级缓存的支持。 查询时,会先查二级缓存,如果二级缓存未命中,再查一级缓存,如果一级缓存也未命中,则执行数据库查询。

ExecutorType 的选择:

在 MyBatis 中,可以通过 Configuration.setDefaultExecutorType(ExecutorType type) 方法 设置默认的 ExecutorType。 也可以在创建 SqlSession 时,通过 SqlSessionFactory.openSession(ExecutorType executorType) 方法 显式指定使用的 ExecutorType

如何选择合适的 ExecutorType?

  • SIMPLE: 默认选择。 适用于大多数简单场景,或者对性能要求不高的情况。 如果不知道选择哪个,选择 SIMPLE 通常是安全的。
  • REUSE: 适用于 需要重复执行相同 SQL 语句 的场景,例如循环查询、分页查询等。 可以提高性能,但需要注意 SQL 语句的完全一致性。
  • BATCH: 适用于 批量插入、批量更新、批量删除等批量操作场景。 可以大幅提升批量操作的性能,但需要 SQL 语句和数据库驱动支持批量执行。
  • CachingExecutor: 不需要显式选择 CachingExecutor 二级缓存的启用和禁用是通过配置 <cache> 元素来实现的。 MyBatis 会 自动在合适的执行器 (例如 SimpleExecutor, ReuseExecutor, BatchExecutor) 之上添加 CachingExecutor 装饰器,如果配置了二级缓存。 开发者无需直接操作 CachingExecutor

总结不同 Executor 实现的区别:

Executor 实现SimpleExecutorReuseExecutorBatchExecutorCachingExecutor
Statement 复用不复用复用相同 SQL批量操作复用取决于被装饰的执行器
批量支持不支持不支持支持取决于被装饰的执行器
缓存管理一级缓存一级缓存一级缓存 (默认不自动刷新)二级缓存 (装饰器)
性能较低中等高 (批量操作)高 (缓存命中)
复杂度最简单简单较复杂装饰器,不直接操作 SQL
适用场景默认, 简单场景重复 SQL批量操作二级缓存场景

在大多数情况下,默认的 SIMPLE 执行器已经足够使用。 如果需要提高性能,可以考虑使用 REUSE 执行器或 BATCH 执行器,或者启用二级缓存。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值