perf: V0.9.1-0.9.3 性能优化(count/featured 全表→聚合、请求内缓存、二级索引、PSI 未读铃铛)

- V0.9.1 (P0): Model::count() 改 SELECT COUNT(*);新增请求内 identity-map 缓存;
  Product::featured() 改 WHERE+ LIMIT 避免全表
- V0.9.2 (P1): schema.sql 内联二级索引 + install/upgrades/009_perf_indexes.sql 幂等迁移
- V0.9.3 (P1): psi_unread_events() 改 COUNT + JSON_CONTAINS,消除每页 all()+循环
This commit is contained in:
2026-08-08 19:47:35 +08:00
parent a2dac3b095
commit 4d36a284ff
5 changed files with 193 additions and 25 deletions
+13
View File
@@ -167,6 +167,19 @@ if (!function_exists('site_url')) {
if (!subsys_user('psi')) return 0;
$uid = (int) ($_SESSION['admin_uid'] ?? 0);
if ($uid <= 0) return 0;
// V0.9.3MySQL 下改用 COUNT + JSON_CONTAINS 聚合,避免每个后台页都 SELECT * 全表拉回再循环计数。
// 语义与旧逻辑一致:统计「当前用户不在 read_by 已读列表」的事件数。
if (\Core\Db::driver() === 'mysql') {
try {
return (int) \Core\Db::query(
"SELECT COUNT(*) FROM psi_events WHERE JSON_CONTAINS(COALESCE(read_by,'[]'), CAST(? AS JSON)) = 0",
[$uid]
)->fetchColumn();
} catch (\Throwable $e) {
// 极端情况(如 read_by 含非法 JSON)回退旧逻辑,保证铃铛数字不报错
}
}
// 文件模式 / MySQL 兜底:无 JSON 函数或异常,保留全表循环(数据量小,可接受)
try {
$events = (new \App\Models\PSI\Event())->all();
} catch (\Throwable $e) {