> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/di-24-zhang-zfs-wen-jian-xi-tong/di-24.6-jie-zfs-diao-you.md).

# 24.6 ZFS 调优

## 技术潜能与现实困境

ZFS 的性能优势与高级特性需要针对性的参数调优才能充分发挥，调优策略依赖具体环境，需结合存储硬件、工作负载特征与使用场景作个性化配置，主要调优方向包括 ARC 缓存大小、记录大小、压缩算法选择等。ZFS 不属于典型的开箱即用型文件系统。

## 调优

调整可调参数，使 ZFS 在不同的工作负载下表现最佳。可以随时通过 sysctl(8) 调整以下值，还可以在 **/boot/loader.conf** 或 **/etc/sysctl.conf** 中永久设置某值。

* `vfs.zfs.arc.max` - ARC 的最大大小。默认值为 `0`，对于 FreeBSD，实际取总内存 - 1 GiB 与总内存的 5/8 中的较大值。此值不得低于 64 MiB。如果系统运行其他守护进程或进程可能需要内存，可以使用较小的值。

  > **注意**
  >
  > 可以使用 sysctl(8) 动态修改 `vfs.zfs.arc.max`。但是系统运行期间无法再将其改回 `0`；此外，若将该设定值调得比当前 ARC 实际占用还低，ARC 将不会主动缩减，必须等到系统出现内存压力时才会触发回收。
* `vfs.zfs.arc.min` - ARC 的最小大小。默认值为 `0`，实际取 32 MiB 与总内存的 1/32 中的较大值。可以调整此值，以防止其他应用程序挤出整个 ARC。
* `vfs.zfs.vdev.min_auto_ashift` - 池创建时自动使用的最低 `ashift`（扇区大小）。该值是 2 的幂。默认值为 `9`，表示 `2^9 = 512`，即 512 字节的扇区大小。为了避免 **写放大** 并获得最佳性能，应将此值设置为池中设备使用的最大扇区大小。常见的驱动器有 4 KB 扇区。使用默认的 `ashift` 值 `9` 与这些驱动器会导致写放大。在这些设备中，单个 4 KB 写入的数据将以八次 512 字节写入的方式写入。ZFS 尝试在创建池时从所有设备读取原生扇区大小，但具有 4 KB 扇区的驱动器为兼容性考虑报告其扇区为 512 字节。在创建池之前将 `vfs.zfs.vdev.min_auto_ashift` 设为 `12`（`2^12 = 4096`），即可强制 ZFS 使用 4 KB 块，从而获得最佳性能。

  > **技巧**
  >
  > 通过 bsdinstall 安装的 FreeBSD ZFS 系统，`vfs.zfs.vdev.min_auto_ashift` 值默认为 `12`，参见源代码文件 **usr.sbin/bsdinstall/scripts/zfsboot**。

  强制使用 4 KB 块在计划升级磁盘的池中也非常有用。目前的磁盘使用 4 KB 扇区，而 `ashift` 值在创建池后无法更改。

  在某些特定情况下，较小的 512 字节块大小可能更为合适。例如，在使用 512 字节磁盘用于数据库或虚拟机存储时，较小的块在小随机读取时会传输更少的数据。这可以在使用较小的 ZFS 记录大小时提供更好的性能。
* `vfs.zfs.prefetch.disable` - 禁用预测性预取。值为 `0` 时启用，值为 `1` 时禁用。默认值为 `0`（启用预测性预取）。预取会将比请求的块大得多的数据块读取到 ARC 中，预期稍后会用到这些数据。如果工作负载有大量随机读取，禁用预取可能因减少不必要的读取而提高性能。注意，此参数仅禁用预测性预取，不影响先验性预取（prescient prefetch，如 `zfs send` 使用的预取），后者永远不会发出最终不被需要的 I/O，因此不会影响性能。
* `vfs.zfs.l2arc.write_max` - 限制每个 L2ARC 设备每秒写入的最大数据量。默认值为 `67108864` 字节（64 MiB）。总 L2ARC 吞吐量随池中缓存设备数量线性增长。
* `vfs.zfs.l2arc.noprefetch` - 是否将预取但未被应用程序使用的缓冲区写入 L2ARC。默认值为 `1`（禁用）。值为 `0` 时启用。禁用时，预取的数据不会缓存到 L2ARC。将此值设为 `0` 可将磁盘上的顺序读取缓存到 L2ARC，并在之后从 L2ARC 提供这些读取服务。当 L2ARC 设备在顺序读取上比池磁盘快得多时，这可能是有益的。
* `vfs.zfs.l2arc.mfuonly` - 控制从 ARC 缓存到 L2ARC 的内容。默认值为 `0`，表示 MRU 和 MFU 的数据和元数据都会被缓存到 L2ARC。设为 `1` 时，仅缓存 MFU 数据和元数据，适用于读写大量不会再次访问的数据时避免浪费 L2ARC 空间的场景。设为 `2` 时，缓存所有元数据（MRU+MFU）但仅缓存 MFU 数据，适用于希望在数据高周转时尽可能多地缓存元数据的场景。
* `vfs.zfs.l2arc.dwpd_limit` - L2ARC 设备的每日写入量（Drive Writes Per Day）限制，以百分比表示，默认值为 `100`。`100` 等于 1.0 DWPD，即每个 L2ARC 设备每天最多写入自身容量一次。较低的值支持分数 DWPD（50 = 0.5 DWPD，30 = 0.3 DWPD，适用于 QLC SSD）。较高的值允许更多写入（300 = 3.0 DWPD）。实际写入速率始终受 `vfs.zfs.l2arc.write_max` 限制。值为 `0` 时禁用 DWPD 速率限制。DWPD 限制仅在初始填充阶段完成且 L2ARC 总容量至少为 `arc_c_max` 的两倍后才生效。
* `vfs.zfs.txg.timeout` - 事务组（transaction group）之间的最大秒数，即脏数据刷写到磁盘的最大间隔。默认值为 `5` 秒。当前事务组写入池中，如果自上一个事务组以来经过了此时间，则启动新的事务组。如果写入了足够的数据，事务组可能会提前触发。较大的值可能因延迟异步写入而提高读取性能，但这可能导致写入事务组时性能不均匀。
* `vfs.zfs.vdev.scrub_min_active` - scrub 操作时每个设备的最小并发 I/O 数。默认值为 `1`。当 vdev 空闲时，并发数自动提升至 `vfs.zfs.vdev.scrub_max_active`。
* `vfs.zfs.vdev.scrub_max_active` - scrub 操作时每个设备的最大并发 I/O 数。默认值为 `3`。增大此值可加快 scrub 完成速度，但会增加读写延迟并降低吞吐量。
* `vfs.zfs.vdev.rebuild_min_active` - sequential rebuild（顺序重建，区别于传统 resilver）操作时每个设备的最小并发 I/O 数。默认值为 `1`。
* `vfs.zfs.vdev.rebuild_max_active` - sequential rebuild 操作时每个设备的最大并发 I/O 数。默认值为 `3`。增大此值可加快 rebuild 完成速度，但会增加读写延迟。
* `vfs.zfs.vdev.nia_delay` - 对于非交互式 I/O（scrub、resilver、移除、初始化和重建），并发 I/O 数限制为各队列的 `min_active`，除非 vdev 处于“空闲”状态。当没有交互式 I/O 活动，且自上次交互式操作以来已完成 `vfs.zfs.vdev.nia_delay` 个非交互式操作后，vdev 被视为“空闲”，非交互式操作的并发数提升至各队列的 `max_active`。默认值为 `5`。
* `vfs.zfs.vdev.nia_credit` - 某些机械硬盘会以较高优先级处理顺序 I/O，导致并发随机 I/O 延迟达到数秒。为防止非交互式 I/O（如 scrub）独占设备，当存在未完成的交互式 I/O 时，最多只能发送 `vfs.zfs.vdev.nia_credit` 个非交互式操作。此强制等待确保机械硬盘在合理时间内处理交互式 I/O。默认值为 `5`。

## 参考文档

与 ZFS 调优相关的文档包括：

* OpenZFS 项目的官方文档 <https://openzfs.github.io/openzfs-docs/index.html>，其中包含专门的性能与调优章节，涵盖模块参数、工作负载调优等内容。
* 《FreeBSD 操作系统设计与实现（第二版）》：包含 ZFS 原理性描述。
* *FreeBSD Mastery: ZFS* 与 *FreeBSD Mastery: Advanced ZFS*：价值有限。
* [Oracle Solaris 管理：ZFS 文件系统](https://docs.oracle.com/cd/E26926_01/html/E25826/index.html)：该文档在 OpenZFS 项目启动之前撰写，不包含 OpenZFS 近十五年来的开发进展，仅供参考。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/di-24-zhang-zfs-wen-jian-xi-tong/di-24.6-jie-zfs-diao-you.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
