跳转至

[ISSUE-0050] 商家列表 chip 截断 50k + 加载慢

用户截图(v0.10.64,228k 数据)反馈: 1. 数据不一致:左侧 sidebar 显 "商家列表 228430"(22w),但 chip "全部 50.0k" 2. 打开列表很卡,加载好久

病灶

src/utils/merchant-stats.ts:31 硬上限 ROWS_CAP = 50_000

const allRows = await selectByQuery('MapTaskData', { limit: ROWS_CAP, ... }) as any[];
// 全表 select 50k → JS for loop 6 个 count → return { total: rows.length, ... };

22w 数据 → 拉 50k 后停 → total = 50_000(cap) vs 真实 228430(sidebar / KPI 走 countAllData() 真实数)→ 用户看到矛盾。

加载慢:每 10s polling → 拉 50k 行(~80-200ms IndexedDB → JS heap)。

1. 无 taskId 走 jsstore count(毫秒级)

countAllData() / scraped / pending 三个 jsstore count 并发:

const [total, scraped, pending] = await Promise.all([
  countByQuery(TABLE, {}),               // 真实总数
  countByQuery(TABLE, { scrape_status: 2 }),
  countByQuery(TABLE, { scrape_status: 0 }),
]);

withEmail / withWebsite / highRating 仍需 50k 采样: - emails 是 array,jsstore 不能查 length - website 非空判断不可靠(jsstore where 仅 equality 安全) - rating >= 4.5 jsstore 支持但保守

但增加 truncated: boolean + sampleLimit: number 字段:

return {
  total,         // 真实数
  scraped,       // 真实数
  pending,       // 真实数
  withEmail,     // 采样数
  withWebsite,   // 采样数
  highRating,    // 采样数
  truncated: total > sample.length,
  sampleLimit: ROWS_CAP,
};

UI banner:truncated 时提示「全部/已挖掘/待挖掘」是真实数;「有邮箱/有网址/高评分」是采样数。

2. 有 taskId 走原全表(保留 v0.10.2 ISSUE-0008 修复)

jsstore where: { taskId } 在升级过的 DB 会喷 logError。保留全表 + JS filter。

3. 降轮询频率:10s → 30s

stats 不需要那么实时(chip 数字大致正确即可)。22w 数据时 30s 一次拉 50k = CPU 占用降 3x。

数据

旧(v0.10.69) 新(v0.10.70)
total 真实数 ❌ 50k cap ✅ 真实(无 taskId 时 jsstore count)
scraped / pending ❌ 50k 采样 ✅ 真实(jsstore count)
withEmail / withWebsite / highRating 50k 采样(无 banner) 50k 采样(有 banner 明示
加载耗时(22w 数据,无 taskId) ~ 100-300ms ~ 80-200ms(节约了 3 个 count,select 50k 仍是大头)
轮询频率 10s 30s
22w 数据 CPU 占用 低 3x

未来优化(不做)

  • withEmail 走 IndexedDB cursor 流式 count(不一次 load all)— 复杂度高,先把 cap 标清楚
  • jsstore range query { rating: { '>=': 4.5 } } — 文档说支持但项目代码未用过,谨慎
  • 完全去掉轮询,改 merchant_data_changed event 触发 — 需 background 在 insert 时发 event

工作流

本次严格 bump → build → sanity check 三步:

 build sync: 0.10.70

相关

  • [[0018-hasemailonly-50k-silent-truncate|0018-hasEmailOnly-50k上限静默截断]] — 同 50k cap 限制,本次相同思路加 banner
  • v0.10.2 jsstore where:taskId 喷 logError 的原始修复(无独立 ISSUE 文件) — 同精神
  • 版本发布流程 — 本次正确顺序的范本