MyBatis 提供了几种不同的 Executor 接口的实现类,这些实现类被称为 执行器类型 (ExecutorType)。 不同的 Executor 实现类采用了不同的 SQL 执行策略,从而在性能、功能和适用场景上有所区别。 MyBatis 默认提供了以下三种主要的 Executor 实现:
SimpleExecutor(简单执行器)ReuseExecutor(复用执行器)BatchExecutor(批量执行器)
除了这三种主要的执行器,MyBatis 还有一个 CachingExecutor (缓存执行器),但 CachingExecutor 并不是一个独立的执行器类型,而是一个 装饰器 (Decorator),它 装饰在其他执行器之上,为其添加二级缓存的支持。
以下是各种 Executor 实现的详细区别:
1. SimpleExecutor (简单执行器)
- 描述:
SimpleExecutor是 MyBatis 默认的执行器类型。 它也是 最简单 的执行器实现。 - 核心特点:
- 每次执行 SQL 语句,都会创建一个新的
Statement对象。 无论执行多少次相同的 SQL 语句 (即使只是参数不同),SimpleExecutor都会重新创建Statement对象。 - 不复用
Statement对象。 - 不支持批量 SQL 执行。
- 每次执行 SQL 语句,都会创建一个新的
- 性能特点:
- 性能相对较低。 由于每次执行 SQL 都需要创建新的
Statement对象,会增加对象创建和销毁的开销,以及Statement预编译的开销 (虽然 JDBC 驱动通常会缓存预编译语句,但仍然有开销)。 - 资源消耗相对较高。 频繁创建
Statement对象会增加资源消耗。
- 性能相对较低。 由于每次执行 SQL 都需要创建新的
- 适用场景:
- 简单查询、少量 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 执行。
- 对于相同的 SQL 语句 (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 执行。 可以将多条 SQL 语句 (例如多个
- 性能特点:
- 性能最高 (针对批量操作)。 批量执行 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本身不处理Statement,Statement的处理仍然由被装饰的执行器负责 (例如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 实现 | SimpleExecutor | ReuseExecutor | BatchExecutor | CachingExecutor |
|---|---|---|---|---|
| Statement 复用 | 不复用 | 复用相同 SQL | 批量操作复用 | 取决于被装饰的执行器 |
| 批量支持 | 不支持 | 不支持 | 支持 | 取决于被装饰的执行器 |
| 缓存管理 | 一级缓存 | 一级缓存 | 一级缓存 (默认不自动刷新) | 二级缓存 (装饰器) |
| 性能 | 较低 | 中等 | 高 (批量操作) | 高 (缓存命中) |
| 复杂度 | 最简单 | 简单 | 较复杂 | 装饰器,不直接操作 SQL |
| 适用场景 | 默认, 简单场景 | 重复 SQL | 批量操作 | 二级缓存场景 |
在大多数情况下,默认的 SIMPLE 执行器已经足够使用。 如果需要提高性能,可以考虑使用 REUSE 执行器或 BATCH 执行器,或者启用二级缓存。

2956

被折叠的 条评论
为什么被折叠?



