diff --git a/TOC.md b/TOC.md
index ed58f67f1945..242202e7ec55 100644
--- a/TOC.md
+++ b/TOC.md
@@ -314,6 +314,7 @@
- [TiKV 线程调优](/tune-tikv-thread-performance.md)
- [TiKV 内存调优](/tune-tikv-memory-performance.md)
- [TiKV Follower Read](/follower-read.md)
+ - [TiKV MVCC 内存引擎](/tikv-in-memory-engine.md)
- [Region 性能调优](/tune-region-performance.md)
- [TiFlash 调优](/tiflash/tune-tiflash-performance.md)
- [下推计算结果缓存](/coprocessor-cache.md)
diff --git a/analyze-slow-queries.md b/analyze-slow-queries.md
index 17dcbc6d70a2..8005c593560e 100644
--- a/analyze-slow-queries.md
+++ b/analyze-slow-queries.md
@@ -96,9 +96,9 @@ summary: 学习如何定位和分析慢查询。
如上图,发给 `10.6.131.78` 的一个 `cop-task` 等待了 110ms 才被执行,可以判断是当时该实例忙,此时可以打开当时的 CPU 监控辅助判断。
-#### 过期 key 多
+#### 过期 MVCC 版本和 key 过多
-如果 TiKV 上过期的数据比较多,在扫描的时候则需要处理这些不必要的数据,影响处理速度。
+如果 TiKV 上过期 MVCC 版本过多,或 GC 历史版本数据的保留时间长,导致累积了过多 MVCC。处理这些不必要的 MVCC 版本会影响扫描速度。
这可以通过 `Total_keys` 和 `Processed_keys` 判断,如果两者相差较大,则说明旧版本的 key 太多:
@@ -108,6 +108,8 @@ summary: 学习如何定位和分析慢查询。
...
```
+TiDB v8.5.0 引入了内存引擎功能,可以加速这类慢查询。详见 [TiKV MVCC 内存引擎](/tikv-in-memory-engine.md)。
+
### 其他关键阶段慢
#### 取 TS 慢
diff --git a/media/tikv-ime-data-organization.png b/media/tikv-ime-data-organization.png
new file mode 100644
index 000000000000..4ccd51f56236
Binary files /dev/null and b/media/tikv-ime-data-organization.png differ
diff --git a/tikv-configuration-file.md b/tikv-configuration-file.md
index dbe4f8099fc6..f041d100d5fc 100644
--- a/tikv-configuration-file.md
+++ b/tikv-configuration-file.md
@@ -1025,7 +1025,7 @@ raftstore 相关的配置项。
+ 最小值:0
+ 单位:秒
-### `evict-cache-on-memory-ratio` 从 v7.5.0 版本开始引入
+### `evict-cache-on-memory-ratio` 从 v7.5.0 版本开始引入
+ 当 TiKV 的内存使用超过系统可用内存的 90%,并且 Raft 缓存条目占用的内存超过已使用内存 * `evict-cache-on-memory-ratio` 时,TiKV 会逐出 Raft 缓存条目。
+ 设置为 `0` 表示禁用该功能。
@@ -1682,7 +1682,7 @@ rocksdb defaultcf titan 相关的配置项。
+ 指定 zstd 字典大小,默认为 `"0KiB"`,表示关闭 zstd 字典压缩,也就是说 Titan 中压缩的是单个 value 值,而 RocksDB 压缩以 Block(默认值为 `32KiB`)为单位。因此当关闭字典压缩、且 value 平均小于 `32KiB` 时,Titan 的压缩率低于 RocksDB。以 JSON 内容为例,Titan 的 Store Size 可能比 RocksDB 高 30% 至 50%。实际压缩率还取决于 value 内容是否适合压缩,以及不同 value 之间的相似性。你可以通过设置 `zstd-dict-size`(比如 `16KiB`)启用 zstd 字典以大幅提高压缩率(实际 Store Size 可以低于 RocksDB),但 zstd 字典压缩在有些负载下会有 10% 左右的性能损失。
+ 默认值:`"0KiB"`
+ 单位:KiB|MiB|GiB
-
+
### `blob-cache-size`
+ Blob 文件的 cache 大小。
@@ -2504,3 +2504,36 @@ Raft Engine 相关的配置项。
+ 设置 TiKV 堆内存分析每次采样的数据量,以 2 的指数次幂向上取整。
+ 默认值:512KiB
+
+## in-memory-engine 从 v8.5.0 版本开始引入
+
+TiKV MVCC 内存引擎 (In-Memory Engine) 在 TiKV 存储层相关的配置项。
+
+### `enable` 从 v8.5.0 版本开始引入
+
+> **注意:**
+>
+> 该配置项支持在配置文件中进行配置,但不支持通过 SQL 语句查询。
+
++ 是否开启内存引擎以加速多版本查询。关于内存引擎的详细信息,参见 [TiKV MVCC 内存引擎](/tikv-in-memory-engine.md)。
++ 默认值:false(即关闭内存引擎)
+
+### `capacity` 从 v8.5.0 版本开始引入
+
+> **注意:**
+>
+> + 开启内存引擎后,`block-cache.capacity` 会自动减少 10%。
+> + 手动配置 `capacity` 时,`block-cache.capacity` 不会自动减少,需手动调整为合适的值以避免 OOM。
+
++ 配置内存引擎可使用的内存大小。最大值为 5 GiB。你可以手动调整配置以使用更多内存。
++ 默认值:系统内存的 10%。
+
+### `gc-run-interval` 从 v8.5.0 版本开始引入
+
++ 控制内存引擎 GC 缓存 MVCC 版本的时间间隔。调小该参数可加快 GC 频率,减少 MVCC 记录,但会增加 GC 的 CPU 消耗,以及增加内存引擎失效的概率。
++ 默认值:3m
+
+### `mvcc-amplification-threshold` 从 v8.5.0 版本开始引入
+
++ 控制内存引擎选取加载 Region 时 MVCC 读放大的阈值。默认为 `10`,表示在某个 Region 中读一行记录需要处理的 MVCC 版本数量超过 10 个时,有可能会被加载到内存引擎中。
++ 默认值:10
diff --git a/tikv-in-memory-engine.md b/tikv-in-memory-engine.md
new file mode 100644
index 000000000000..7e0b3291afa0
--- /dev/null
+++ b/tikv-in-memory-engine.md
@@ -0,0 +1,134 @@
+---
+title: TiKV MVCC 内存引擎
+summary: 了解内存引擎的适用场景和工作原理,使用内存引擎加速多版本记录查询。
+---
+
+# TiKV MVCC 内存引擎
+
+TiKV MVCC 内存引擎 (In-Memory Engine, IME) 主要用于加速需要扫描大量 MVCC 历史版本的查询,即[查询扫描的总共版本数量 (`total_keys`) 远大于处理的版本数量 (`processed_keys`)](/analyze-slow-queries.md#过期-mvcc-版本和-key-过多)。
+
+TiKV MVCC 内存引擎适用于以下场景:
+
+- 业务需要查询频繁更新或删除的记录。
+- 业务需要调整 [`tidb_gc_life_time`](/garbage-collection-configuration.md#gc-配置),使 TiDB 保留较长时间的历史版本(比如 24 小时)。
+
+## 工作原理
+
+TiKV MVCC 内存引擎在内存中缓存最近写入的 MVCC 版本,并实现独立于 TiDB 的 MVCC GC 机制,使其可快速 GC 内存中的 MVCC 记录,从而减少查询时扫描版本的个数,以达到降低请求延时和减少 CPU 开销的效果。
+
+下图为 TiKV 如何组织 MVCC 版本的示意图:
+
+![IME 通过缓存近期的版本以减少 CPU 开销](/media/tikv-ime-data-organization.png)
+
+以上示意图中共有 2 行记录,每行记录各有 9 个 MVCC 版本。在开启内存引擎和未开启内存引擎的情况下,行为对比如下:
+
+- 左侧(未开启内存引擎):表中记录按主键升序保存在 RocksDB 中,相同行的 MVCC 版本紧邻在一起。
+- 右侧(开启了内存引擎):RocksDB 中的数据与左侧一致,同时内存引擎缓存了 2 行记录最新的 2 个 MVCC 版本。
+- 当 TiKV 处理一个范围为 `[k1, k2]`,开始时间戳为 `8` 的扫描请求时:
+ - 左侧未开启内存引擎时需要处理 11 个 MVCC 版本。
+ - 右侧开启内存引擎时只需处理 4 个 MVCC 版本,因此减少了请求延时和 CPU 消耗。
+- 当 TiKV 处理一个范围为 `[k1, k2]`,开始时间戳为 `7` 的扫描请求时:
+ - 由于右侧缺少需要读取的历史版本,因此内存引擎缓存失效,回退到读取 RocksDB 中的数据。
+
+## 使用方式
+
+如果要开启 TiKV MVCC 内存引擎 (IME) 功能,需要调整 TiKV 配置并重启 TiKV。以下是配置说明:
+
+```toml
+[in-memory-engine]
+# 该参数为内存引擎功能的开关,默认为 false,调整为 true 即可开启。
+enable = false
+
+# 该参数控制内存引擎可使用的内存大小。默认值为系统内存的 10%,同时最大值为 5 GiB,
+# 可通过手动调整配置以使用更多内存。
+# 注意:当内存引擎开启后,block-cache.capacity 会减少 10%。
+capacity = "5GiB"
+
+# 该参数控制内存引擎 GC 缓存 MVCC 的版本的时间间隔。
+# 默认为 3 分钟,代表每 3 分钟 GC 一次缓存的 MVCC 版本。
+# 调小该参数可加快 GC 频率,减少 MVCC 记录,但会增加 GC CPU 的消耗和增加内存引擎失效的概率。
+gc-run-interval = "3m"
+
+# 该参数控制内存引擎选取加载 Region 时 MVCC 读放大的阈值。
+# 默认为 10,表示在某个 Region 中读一行记录需要处理的 MVCC 版本数量超过 10 个时,将有可能会被加载到内存引擎中。
+mvcc-amplification-threshold = 10
+```
+
+> **注意:**
+>
+> + 内存引擎默认关闭,并且从关闭状态修改为开启状态后,需要重启 TiKV。
+> + 除 `enable` 之外,其他配置都可以动态调整。
+
+### 自动加载
+
+开启内存引擎之后,TiKV 会根据 Region 的读流量和 MVCC 放大程度,选择要自动加载的 Region。具体流程如下:
+
+1. Region 按照最近时间段的 `next` (RocksDB Iterator next API) 和 `prev` (RocksDB Iterator prev API) 次数进行排序。
+2. 使用 `mvcc-amplification-threshold` 配置项对 Region 进行过滤,该配置项的默认值为 `10`。MVCC amplification 衡量读放大程度,计算公式为 (`next` + `prev`) / `processed_keys`)。
+3. 载入前 N 个 MVCC 放大严重的 Region,其中 N 基于内存估算而来。
+
+内存引擎也会定期驱逐 Region。具体流程如下:
+
+1. 内存引擎会驱逐那些读流量过小或者 MVCC 放大程度过低的 Region。
+2. 如果内存使用达到了 `capacity` 的 90%,并且有新的 Region 需要被载入,那么内存引擎会根据读取流量来筛选 Region 并进行驱逐。
+
+## 兼容性
+
++ [BR](/br/br-use-overview.md):内存引擎与 BR 可同时使用,但 BR restore 会驱逐内存引擎中涉及恢复的 Region,BR restore 完成后,如果对应 Region 还是热点,则会被内存引擎自动加载。
++ [TiDB Lightning](/tidb-lightning/tidb-lightning-overview.md):内存引擎与 TiDB Lightning 可同时使用,但 TiDB Lightning 的物理导入模式会驱逐内存引擎中涉及恢复的 Region,TiDB Lightning 使用物理导入模式完成导入数据后,如果对应 Region 还是热点,则会被内存引擎自动加载。
++ [Follower Read](/develop/dev-guide-use-follower-read.md) 与 [Stale Read](/develop/dev-guide-use-stale-read.md):内存引擎可与这两个特性同时开启,但内存引擎只能加速 Leader 上的 coprocessor 请求,无法加速 Follower Read 和 Stale Read。
++ [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md):内存引擎与 Flashback 可同时使用,但 Flashback 会导致内存引擎缓存失效。Flashback 完成后,内存引擎会自动加载热点 Region。
+
+## FAQ
+
+### 内存引擎能否减少写入延时,提高写入吞吐?
+
+不能。内存引擎只能加速扫描了大量 MVCC 版本的读请求。
+
+### 如何判断内存引擎是否能改善我的场景?
+
+可以通过执行以下 SQL 语句查看是否存在 `Total_keys` 远大于 `Process_keys` 的慢查询:
+
+```sql
+SELECT
+ Time,
+ DB,
+ Index_names,
+ Process_keys,
+ Total_keys,
+ CONCAT(
+ LEFT(REGEXP_REPLACE(Query, '\\s+', ' '), 20),
+ '...',
+ RIGHT(REGEXP_REPLACE(Query, '\\s+', ' '), 10)
+ ) as Query,
+ Query_time,
+ Cop_time,
+ Process_time
+FROM
+ INFORMATION_SCHEMA.SLOW_QUERY
+WHERE
+ Is_internal = 0
+ AND Cop_time > 1
+ AND Process_keys > 0
+ AND Total_keys / Process_keys >= 10
+ AND Time >= NOW() - INTERVAL 10 MINUTE
+ORDER BY Total_keys DESC
+LIMIT 5;
+```
+
+示例:
+
+以下结果显示 `db1.tbl1` 表上存在 MVCC 放大严重的查询,TiKV 在处理 1358517 个 MVCC 版本后,仅返回了 2 个版本。
+
+```
++----------------------------+-----+-------------------+--------------+------------+-----------------------------------+--------------------+--------------------+--------------------+
+| Time | DB | Index_names | Process_keys | Total_keys | Query | Query_time | Cop_time | Process_time |
++----------------------------+-----+-------------------+--------------+------------+-----------------------------------+--------------------+--------------------+--------------------+
+| 2024-11-18 11:56:10.303228 | db1 | [tbl1:some_index] | 2 | 1358517 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.2581352350000001 | 1.25651062 | 1.251837479 |
+| 2024-11-18 11:56:11.556257 | db1 | [tbl1:some_index] | 2 | 1358231 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.252694002 | 1.251129038 | 1.240532546 |
+| 2024-11-18 12:00:10.553331 | db1 | [tbl1:some_index] | 2 | 1342914 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.473941872 | 1.4720495900000001 | 1.3666103170000001 |
+| 2024-11-18 12:01:52.122548 | db1 | [tbl1:some_index] | 2 | 1128064 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.058942591 | 1.056853228 | 1.023483875 |
+| 2024-11-18 12:01:52.107951 | db1 | [tbl1:some_index] | 2 | 1128064 | SELECT * FROM tbl1 ... LIMIT 1 ; | 1.044847031 | 1.042546122 | 0.934768555 |
++----------------------------+-----+-------------------+--------------+------------+-----------------------------------+--------------------+--------------------+--------------------+
+5 rows in set (1.26 sec)
+```
diff --git a/troubleshoot-hot-spot-issues.md b/troubleshoot-hot-spot-issues.md
index 0abce246dc27..24cedca4862f 100644
--- a/troubleshoot-hot-spot-issues.md
+++ b/troubleshoot-hot-spot-issues.md
@@ -176,3 +176,7 @@ TiDB 的 Coprocessor Cache 功能支持下推计算结果缓存。开启该功
## 打散读热点
在读热点场景中,热点 TiKV 无法及时处理读请求,导致读请求排队。但是,此时并非所有 TiKV 资源都已耗尽。为了降低延迟,TiDB v7.1.0 引入了负载自适应副本读取功能,允许从其他 TiKV 节点读取副本,而无需在热点 TiKV 节点排队等待。你可以通过 [`tidb_load_based_replica_read_threshold`](/system-variables.md#tidb_load_based_replica_read_threshold-从-v700-版本开始引入) 系统变量控制读请求的排队长度。当 leader 节点的预估排队时间超过该阈值时,TiDB 会优先从 follower 节点读取数据。在读热点的情况下,与不打散读热点相比,该功能可提高读取吞吐量 70%~200%。
+
+## 使用 TiKV MVCC 内存引擎缓解因多版本导致的读热点
+
+在 GC 历史版本数据的保留时间过长、频繁更新或删除时,可能会因扫描大量 MVCC 版本而导致读热点。针对这类热点,可通过开启 [TiKV MVCC 内存引擎](/tikv-in-memory-engine.md)功能缓解。