[Performance] 优化 D1 高频查询与写入,支持大规模用户邮箱
Author: dreamhunter2333Created Aug 6, 2026Updated Aug 9, 2026
Labelsenhancement
背景
该 issue 只跟踪已经确认会造成大量 D1 查询或写入的高频热点,不处理邮件解析速度,也不继续加入没有实际需求的接口参数和低频微优化。
已完成
✅ 地址活动时间写入限频(#1104)
-
updateAddressUpdatedAt仅更新updated_at为空或超过 1 天的地址。 -
/user_api/settings对用户名下地址使用相同的 1 天保活条件。 - 密码、配置、Passkey counter 和发信计数等真实数据更新不受保活限频影响。
- 增加 E2E 回归测试,验证一天内重复访问不会重复更新近期地址。
- 使用固定 1 天窗口,不增加额外环境变量或配置项。
✅ 大用户地址分页与邮件归属查询(#1105)
-
GET /user_api/bind_address支持limit、offset服务端分页;默认返回前 20 条。 - 用户地址管理页面只请求当前页,不再加载并渲染全部绑定地址。
- 地址邮件数和发件数只对当前请求页计算。
- 仅第一页查询总数,后续页面不重复执行总数查询。
- 用户邮件列表使用数据库 JOIN 校验地址归属,不再加载全部地址并拼接超长
IN (...)。 - 删除用户邮件使用
EXISTS在数据库侧校验归属。 - 保留旧地址返回字段并隐藏
password。 - 增加 API 和浏览器 E2E,覆盖分页、字段兼容和跨用户邮件隔离。
- 更新中英文 CHANGELOG 和 API 文档。
已确认的设计:
- 不增加后端地址搜索;现有搜索仍由前端处理。
- 不增加
with_counts、with_total等开关。 - 地址选择器和用户邮件筛选最多读取前 100 个绑定地址。
- 不支持一次请求获取全部绑定地址。
待实现
P1:高频清理任务限制扫描量和执行时间
当前定时清理可能扫描或删除全部符合条件的数据,地址关联数据清理还会重复执行相同候选子查询。数据量大时容易占用大量 D1 rows read/write,并导致 Worker 超时。
目标不是单次清空,而是每次快速处理一小批,剩余数据交给后续定时任务。
- 每种内置清理任务每次只选择固定数量的候选数据,不在同一次请求或定时任务中循环到清空。
-
mails、mails_unknow、sendbox先按已建立索引的created_at选取有限 ID,再按 ID 删除。 -
inactiveAddress使用updated_at索引有限选取地址。 -
addressCreated、unboundAddress、emptyAddress先按created_at索引缩小候选范围,再使用NOT EXISTS做归属或邮件检查。 - 地址类清理只查询一次本批次的
id/name,后续关联表清理复用这批快照,不再为每张表重复扫描 address。 - 剩余符合条件的数据留给下一次定时任务;手动清理需要继续时可再次执行。
- 批次上限使用代码内固定值,不增加环境变量或管理配置。
- 使用
EXPLAIN QUERY PLAN确认候选查询使用现有created_at、updated_at、address、address_id索引,不新增或删除索引。 - 增加 E2E,验证单次不会超过上限、不会误删,并验证后续执行能够继续处理剩余数据。
实现时不依赖 DELETE ... LIMIT,使用有限候选子查询:
DELETE FROM target_table
WHERE id IN (
SELECT id
FROM target_table
WHERE created_at < datetime('now', ?)
ORDER BY created_at, id
LIMIT ?
)地址类清理先查询一批固定候选,再通过 DB.batch 清理这些地址的关联数据和地址记录。单次批处理结束后立即返回,不继续循环。
暂不实施
以下内容属于低频操作、没有明确收益,或会显著扩大改动范围,不再作为本 issue 的验收要求:
- 发信计数和历史计数清理优化;当前发信属于低频操作。
- 邮件解析性能优化。
- 为邮件列表设计新的元数据表、批量回填旧数据或游标分页。
- 后端地址搜索以及可选统计参数。
- 管理员统计合并、Webhook 测试邮件随机查询调整。
- 地址转移流程重构。
saveSetting、request-scope settings 缓存和地址创建返回 ID 等低频微优化。- 删除、调整或新增索引。
如果后续监控或真实数据证明这些位置成为高频热点,再分别创建独立 issue。
剩余验收标准
- 所有内置清理任务都有固定单次候选上限,不执行无界扫描或大删除。
- 候选查询通过现有索引定位过期数据。
- 单次清理后允许保留符合条件的数据,后续执行能够继续处理。
- 地址及关联数据清理不会产生残留或误删。
- 新增对应 E2E,并更新中英文 CHANGELOG。
Source: dreamhunter2333/cloudflare_temp_email